# flake8: noqa
from __future__ import unicode_literals

from .abc import (
    ABCIE,
    ABCIViewIE,
)
from .abcnews import (
    AbcNewsIE,
    AbcNewsVideoIE,
)
from .abcotvs import (
    ABCOTVSIE,
    ABCOTVSClipsIE,
)
from .academicearth import AcademicEarthCourseIE
from .acast import (
    ACastIE,
    ACastChannelIE,
)
from .adn import ADNIE
from .adobeconnect import AdobeConnectIE
from .adobetv import (
    AdobeTVEmbedIE,
    AdobeTVIE,
    AdobeTVShowIE,
    AdobeTVChannelIE,
    AdobeTVVideoIE,
)
from .adultswim import AdultSwimIE
from .aenetworks import (
    AENetworksIE,
    AENetworksCollectionIE,
    AENetworksShowIE,
    HistoryTopicIE,
    HistoryPlayerIE,
    BiographyIE,
)
from .afreecatv import AfreecaTVIE
from .airmozilla import AirMozillaIE
from .aljazeera import AlJazeeraIE
from .alphaporno import AlphaPornoIE
from .amara import AmaraIE
from .alura import (
    AluraIE,
    AluraCourseIE
)
from .amcnetworks import AMCNetworksIE
from .animelab import (
    AnimeLabIE,
    AnimeLabShowsIE,
)
from .americastestkitchen import (
    AmericasTestKitchenIE,
    AmericasTestKitchenSeasonIE,
)
from .animeondemand import AnimeOnDemandIE
from .anvato import AnvatoIE
from .aol import AolIE
from .allocine import AllocineIE
from .aliexpress import AliExpressLiveIE
from .apa import APAIE
from .aparat import AparatIE
from .appleconnect import AppleConnectIE
from .appletrailers import (
    AppleTrailersIE,
    AppleTrailersSectionIE,
)
from .applepodcasts import ApplePodcastsIE
from .archiveorg import (
    ArchiveOrgIE,
    YoutubeWebArchiveIE,
)
from .arcpublishing import ArcPublishingIE
from .arkena import ArkenaIE
from .ard import (
    ARDBetaMediathekIE,
    ARDIE,
    ARDMediathekIE,
)
from .arte import (
    ArteTVIE,
    ArteTVEmbedIE,
    ArteTVPlaylistIE,
)
from .arnes import ArnesIE
from .asiancrush import (
    AsianCrushIE,
    AsianCrushPlaylistIE,
)
from .atresplayer import AtresPlayerIE
from .atttechchannel import ATTTechChannelIE
from .atvat import ATVAtIE
from .audimedia import AudiMediaIE
from .audioboom import AudioBoomIE
from .audiomack import AudiomackIE, AudiomackAlbumIE
from .audius import (
    AudiusIE,
    AudiusTrackIE,
    AudiusPlaylistIE,
    AudiusProfileIE,
)
from .awaan import (
    AWAANIE,
    AWAANVideoIE,
    AWAANLiveIE,
    AWAANSeasonIE,
)
from .azmedien import AZMedienIE
from .baidu import BaiduVideoIE
from .bandaichannel import BandaiChannelIE
from .bandcamp import (
    BandcampIE,
    BandcampAlbumIE,
    BandcampWeeklyIE,
    BandcampMusicIE,
)
from .bannedvideo import BannedVideoIE
from .bbc import (
    BBCCoUkIE,
    BBCCoUkArticleIE,
    BBCCoUkIPlayerEpisodesIE,
    BBCCoUkIPlayerGroupIE,
    BBCCoUkPlaylistIE,
    BBCIE,
)
from .beeg import BeegIE
from .behindkink import BehindKinkIE
from .bellmedia import BellMediaIE
from .beatport import BeatportIE
from .bet import BetIE
from .bfi import BFIPlayerIE
from .bfmtv import (
    BFMTVIE,
    BFMTVLiveIE,
    BFMTVArticleIE,
)
from .bibeltv import BibelTVIE
from .bigflix import BigflixIE
from .bild import BildIE
from .bilibili import (
    BiliBiliIE,
    BiliBiliSearchIE,
    BilibiliCategoryIE,
    BiliBiliBangumiIE,
    BilibiliAudioIE,
    BilibiliAudioAlbumIE,
    BiliBiliPlayerIE,
    BilibiliChannelIE,
)
from .biobiochiletv import BioBioChileTVIE
from .bitchute import (
    BitChuteIE,
    BitChuteChannelIE,
)
from .bitwave import (
    BitwaveReplayIE,
    BitwaveStreamIE,
)
from .biqle import BIQLEIE
from .blackboardcollaborate import BlackboardCollaborateIE
from .bleacherreport import (
    BleacherReportIE,
    BleacherReportCMSIE,
)
from .bloomberg import BloombergIE
from .bokecc import BokeCCIE
from .bongacams import BongaCamsIE
from .bostonglobe import BostonGlobeIE
from .box import BoxIE
from .bpb import BpbIE
from .br import (
    BRIE,
    BRMediathekIE,
)
from .bravotv import BravoTVIE
from .breakcom import BreakIE
from .brightcove import (
    BrightcoveLegacyIE,
    BrightcoveNewIE,
)
from .businessinsider import BusinessInsiderIE
from .buzzfeed import BuzzFeedIE
from .byutv import BYUtvIE
from .c56 import C56IE
from .camdemy import (
    CamdemyIE,
    CamdemyFolderIE
)
from .cammodels import CamModelsIE
from .camwithher import CamWithHerIE
from .canalplus import CanalplusIE
from .canalc2 import Canalc2IE
from .canvas import (
    CanvasIE,
    CanvasEenIE,
    VrtNUIE,
    DagelijkseKostIE,
)
from .carambatv import (
    CarambaTVIE,
    CarambaTVPageIE,
)
from .cartoonnetwork import CartoonNetworkIE
from .cbc import (
    CBCIE,
    CBCPlayerIE,
    CBCWatchVideoIE,
    CBCWatchIE,
    CBCOlympicsIE,
)
from .cbs import CBSIE
from .cbslocal import (
    CBSLocalIE,
    CBSLocalArticleIE,
)
from .cbsinteractive import CBSInteractiveIE
from .cbsnews import (
    CBSNewsEmbedIE,
    CBSNewsIE,
    CBSNewsLiveVideoIE,
)
from .cbssports import (
    CBSSportsEmbedIE,
    CBSSportsIE,
    TwentyFourSevenSportsIE,
)
from .ccc import (
    CCCIE,
    CCCPlaylistIE,
)
from .ccma import CCMAIE
from .cctv import CCTVIE
from .cda import CDAIE
from .ceskatelevize import (
    CeskaTelevizeIE,
    CeskaTelevizePoradyIE,
)
from .channel9 import Channel9IE
from .charlierose import CharlieRoseIE
from .chaturbate import ChaturbateIE
from .chilloutzone import ChilloutzoneIE
from .chirbit import (
    ChirbitIE,
    ChirbitProfileIE,
)
from .cinchcast import CinchcastIE
from .cinemax import CinemaxIE
from .ciscolive import (
    CiscoLiveSessionIE,
    CiscoLiveSearchIE,
)
from .cjsw import CJSWIE
from .cliphunter import CliphunterIE
from .clippit import ClippitIE
from .cliprs import ClipRsIE
from .clipsyndicate import ClipsyndicateIE
from .closertotruth import CloserToTruthIE
from .cloudflarestream import CloudflareStreamIE
from .cloudy import CloudyIE
from .clubic import ClubicIE
from .clyp import ClypIE
from .cmt import CMTIE
from .cnbc import (
    CNBCIE,
    CNBCVideoIE,
)
from .cnn import (
    CNNIE,
    CNNBlogsIE,
    CNNArticleIE,
)
from .coub import CoubIE
from .comedycentral import (
    ComedyCentralIE,
    ComedyCentralTVIE,
)
from .commonmistakes import CommonMistakesIE, UnicodeBOMIE
from .commonprotocols import (
    MmsIE,
    RtmpIE,
    ViewSourceIE,
)
from .condenast import CondeNastIE
from .contv import CONtvIE
from .corus import CorusIE
from .cracked import CrackedIE
from .crackle import CrackleIE
from .crooksandliars import CrooksAndLiarsIE
from .crunchyroll import (
    CrunchyrollIE,
    CrunchyrollShowPlaylistIE
)
from .cspan import CSpanIE
from .ctsnews import CtsNewsIE
from .ctv import CTVIE
from .ctvnews import CTVNewsIE
from .cultureunplugged import CultureUnpluggedIE
from .curiositystream import (
    CuriosityStreamIE,
    CuriosityStreamCollectionIE,
)
from .cwtv import CWTVIE
from .dailymail import DailyMailIE
from .dailymotion import (
    DailymotionIE,
    DailymotionPlaylistIE,
    DailymotionUserIE,
)
from .daum import (
    DaumIE,
    DaumClipIE,
    DaumPlaylistIE,
    DaumUserIE,
)
from .dbtv import DBTVIE
from .dctp import DctpTvIE
from .deezer import (
    DeezerPlaylistIE,
    DeezerAlbumIE,
)
from .democracynow import DemocracynowIE
from .dfb import DFBIE
from .dhm import DHMIE
from .digg import DiggIE
from .discoveryplusindia import (
    DiscoveryPlusIndiaIE,
    DiscoveryPlusIndiaShowIE,
)
from .dotsub import DotsubIE
from .douyin import DouyinIE
from .douyutv import (
    DouyuShowIE,
    DouyuTVIE,
)
from .dplay import (
    DPlayIE,
    DiscoveryPlusIE,
    HGTVDeIE,
    ScienceChannelIE
)
from .dreisat import DreiSatIE
from .drbonanza import DRBonanzaIE
from .drtuber import DrTuberIE
from .drtv import (
    DRTVIE,
    DRTVLiveIE,
)
from .dtube import DTubeIE
from .dvtv import DVTVIE
from .duboku import (
    DubokuIE,
    DubokuPlaylistIE
)
from .dumpert import DumpertIE
from .defense import DefenseGouvFrIE
from .discovery import DiscoveryIE
from .discoverygo import (
    DiscoveryGoIE,
    DiscoveryGoPlaylistIE,
)
from .discoverynetworks import DiscoveryNetworksDeIE
from .discoveryvr import DiscoveryVRIE
from .disney import DisneyIE
from .dispeak import DigitallySpeakingIE
from .doodstream import DoodStreamIE
from .dropbox import DropboxIE
from .dw import (
    DWIE,
    DWArticleIE,
)
from .eagleplatform import EaglePlatformIE
from .ebaumsworld import EbaumsWorldIE
from .echomsk import EchoMskIE
from .egghead import (
    EggheadCourseIE,
    EggheadLessonIE,
)
from .ehow import EHowIE
from .eighttracks import EightTracksIE
from .einthusan import EinthusanIE
from .eitb import EitbIE
from .ellentube import (
    EllenTubeIE,
    EllenTubeVideoIE,
    EllenTubePlaylistIE,
)
from .elonet import ElonetIE
from .elpais import ElPaisIE
from .embedly import EmbedlyIE
from .engadget import EngadgetIE
from .epicon import (
    EpiconIE,
    EpiconSeriesIE,
)
from .eporner import EpornerIE
from .eroprofile import (
    EroProfileIE,
    EroProfileAlbumIE,
)
from .escapist import EscapistIE
from .espn import (
    ESPNIE,
    ESPNArticleIE,
    FiveThirtyEightIE,
)
from .esri import EsriVideoIE
from .europa import EuropaIE
from .expotv import ExpoTVIE
from .expressen import ExpressenIE
from .extremetube import ExtremeTubeIE
from .eyedotv import EyedoTVIE
from .facebook import (
    FacebookIE,
    FacebookPluginsVideoIE,
)
from .fancode import (
    FancodeVodIE,
    FancodeLiveIE
)

from .faz import FazIE
from .fc2 import (
    FC2IE,
    FC2EmbedIE,
)
from .fczenit import FczenitIE
from .filmmodu import FilmmoduIE
from .filmon import (
    FilmOnIE,
    FilmOnChannelIE,
)
from .filmweb import FilmwebIE
from .firsttv import FirstTVIE
from .fivemin import FiveMinIE
from .fivetv import FiveTVIE
from .flickr import FlickrIE
from .folketinget import FolketingetIE
from .footyroom import FootyRoomIE
from .formula1 import Formula1IE
from .fourtube import (
    FourTubeIE,
    PornTubeIE,
    PornerBrosIE,
    FuxIE,
)
from .fox import FOXIE
from .fox9 import (
    FOX9IE,
    FOX9NewsIE,
)
from .foxgay import FoxgayIE
from .foxnews import (
    FoxNewsIE,
    FoxNewsArticleIE,
)
from .foxsports import FoxSportsIE
from .franceculture import FranceCultureIE
from .franceinter import FranceInterIE
from .francetv import (
    FranceTVIE,
    FranceTVSiteIE,
    FranceTVEmbedIE,
    FranceTVInfoIE,
    FranceTVInfoSportIE,
    FranceTVJeunesseIE,
    GenerationWhatIE,
    CultureboxIE,
)
from .freesound import FreesoundIE
from .freespeech import FreespeechIE
from .freshlive import FreshLiveIE
from .frontendmasters import (
    FrontendMastersIE,
    FrontendMastersLessonIE,
    FrontendMastersCourseIE
)
from .fujitv import FujiTVFODPlus7IE
from .funimation import (
    FunimationIE,
    FunimationPageIE,
    FunimationShowIE,
)
from .funk import FunkIE
from .fusion import FusionIE
from .gab import GabTVIE
from .gaia import GaiaIE
from .gameinformer import GameInformerIE
from .gamespot import GameSpotIE
from .gamestar import GameStarIE
from .gaskrank import GaskrankIE
from .gazeta import GazetaIE
from .gdcvault import GDCVaultIE
from .gedidigital import GediDigitalIE
from .generic import GenericIE
from .gfycat import GfycatIE
from .giantbomb import GiantBombIE
from .giga import GigaIE
from .glide import GlideIE
from .globo import (
    GloboIE,
    GloboArticleIE,
)
from .go import GoIE
from .godtube import GodTubeIE
from .golem import GolemIE
from .googledrive import GoogleDriveIE
from .googlepodcasts import (
    GooglePodcastsIE,
    GooglePodcastsFeedIE,
)
from .googlesearch import GoogleSearchIE
from .goshgay import GoshgayIE
from .gputechconf import GPUTechConfIE
from .groupon import GrouponIE
from .hbo import HBOIE
from .hearthisat import HearThisAtIE
from .heise import HeiseIE
from .hellporno import HellPornoIE
from .helsinki import HelsinkiIE
from .hentaistigma import HentaiStigmaIE
from .hgtv import HGTVComShowIE
from .hketv import HKETVIE
from .hidive import HiDiveIE
from .historicfilms import HistoricFilmsIE
from .hitbox import HitboxIE, HitboxLiveIE
from .hitrecord import HitRecordIE
from .hornbunny import HornBunnyIE
from .hotnewhiphop import HotNewHipHopIE
from .hotstar import (
    HotStarIE,
    HotStarPlaylistIE,
    HotStarSeriesIE,
)
from .howcast import HowcastIE
from .howstuffworks import HowStuffWorksIE
from .hrfensehen import HRFernsehenIE
from .hrti import (
    HRTiIE,
    HRTiPlaylistIE,
)
from .huajiao import HuajiaoIE
from .huffpost import HuffPostIE
from .hungama import (
    HungamaIE,
    HungamaSongIE,
    HungamaAlbumPlaylistIE,
)
from .hypem import HypemIE
from .ign import (
    IGNIE,
    IGNVideoIE,
    IGNArticleIE,
)
from .iheart import (
    IHeartRadioIE,
    IHeartRadioPodcastIE,
)
from .imdb import (
    ImdbIE,
    ImdbListIE
)
from .imgur import (
    ImgurIE,
    ImgurAlbumIE,
    ImgurGalleryIE,
)
from .ina import InaIE
from .inc import IncIE
from .indavideo import IndavideoEmbedIE
from .infoq import InfoQIE
from .instagram import (
    InstagramIE,
    InstagramUserIE,
    InstagramTagIE,
)
from .internazionale import InternazionaleIE
from .internetvideoarchive import InternetVideoArchiveIE
from .iprima import IPrimaIE
from .iqiyi import IqiyiIE
from .ir90tv import Ir90TvIE
from .itv import (
    ITVIE,
    ITVBTCCIE,
)
from .ivi import (
    IviIE,
    IviCompilationIE
)
from .ivideon import IvideonIE
from .iwara import IwaraIE
from .izlesene import IzleseneIE
from .jamendo import (
    JamendoIE,
    JamendoAlbumIE,
)
from .jeuxvideo import JeuxVideoIE
from .jove import JoveIE
from .joj import JojIE
from .jwplatform import JWPlatformIE
from .kakao import KakaoIE
from .kaltura import KalturaIE
from .kankan import KankanIE
from .karaoketv import KaraoketvIE
from .karrierevideos import KarriereVideosIE
from .keezmovies import KeezMoviesIE
from .ketnet import KetnetIE
from .khanacademy import (
    KhanAcademyIE,
    KhanAcademyUnitIE,
)
from .kickstarter import KickStarterIE
from .kinja import KinjaEmbedIE
from .kinopoisk import KinoPoiskIE
from .konserthusetplay import KonserthusetPlayIE
from .krasview import KrasViewIE
from .ku6 import Ku6IE
from .kusi import KUSIIE
from .kuwo import (
    KuwoIE,
    KuwoAlbumIE,
    KuwoChartIE,
    KuwoSingerIE,
    KuwoCategoryIE,
    KuwoMvIE,
)
from .la7 import (
    LA7IE,
    LA7PodcastEpisodeIE,
    LA7PodcastIE,
)
from .laola1tv import (
    Laola1TvEmbedIE,
    Laola1TvIE,
    EHFTVIE,
    ITTFIE,
)
from .lbry import (
    LBRYIE,
    LBRYChannelIE,
)
from .lci import LCIIE
from .lcp import (
    LcpPlayIE,
    LcpIE,
)
from .lecture2go import Lecture2GoIE
from .lecturio import (
    LecturioIE,
    LecturioCourseIE,
    LecturioDeCourseIE,
)
from .leeco import (
    LeIE,
    LePlaylistIE,
    LetvCloudIE,
)
from .lego import LEGOIE
from .lemonde import LemondeIE
from .lenta import LentaIE
from .libraryofcongress import LibraryOfCongressIE
from .libsyn import LibsynIE
from .lifenews import (
    LifeNewsIE,
    LifeEmbedIE,
)
from .limelight import (
    LimelightMediaIE,
    LimelightChannelIE,
    LimelightChannelListIE,
)
from .line import (
    LineTVIE,
    LineLiveIE,
    LineLiveChannelIE,
)
from .linkedin import (
    LinkedInLearningIE,
    LinkedInLearningCourseIE,
)
from .linuxacademy import LinuxAcademyIE
from .litv import LiTVIE
from .livejournal import LiveJournalIE
from .livestream import (
    LivestreamIE,
    LivestreamOriginalIE,
    LivestreamShortenerIE,
)
from .lnkgo import LnkGoIE
from .localnews8 import LocalNews8IE
from .lovehomeporn import LoveHomePornIE
from .lrt import LRTIE
from .lynda import (
    LyndaIE,
    LyndaCourseIE
)
from .m6 import M6IE
from .magentamusik360 import MagentaMusik360IE
from .mailru import (
    MailRuIE,
    MailRuMusicIE,
    MailRuMusicSearchIE,
)
from .malltv import MallTVIE
from .mangomolo import (
    MangomoloVideoIE,
    MangomoloLiveIE,
)
from .manoto import (
    ManotoTVIE,
    ManotoTVShowIE,
    ManotoTVLiveIE,
)
from .manyvids import ManyVidsIE
from .maoritv import MaoriTVIE
from .markiza import (
    MarkizaIE,
    MarkizaPageIE,
)
from .massengeschmacktv import MassengeschmackTVIE
from .matchtv import MatchTVIE
from .mdr import MDRIE
from .medaltv import MedalTVIE
from .mediaset import MediasetIE
from .mediasite import (
    MediasiteIE,
    MediasiteCatalogIE,
    MediasiteNamedCatalogIE,
)
from .medici import MediciIE
from .megaphone import MegaphoneIE
from .meipai import MeipaiIE
from .melonvod import MelonVODIE
from .meta import METAIE
from .metacafe import MetacafeIE
from .metacritic import MetacriticIE
from .mgoon import MgoonIE
from .mgtv import MGTVIE
from .miaopai import MiaoPaiIE
from .microsoftvirtualacademy import (
    MicrosoftVirtualAcademyIE,
    MicrosoftVirtualAcademyCourseIE,
)
from .mildom import (
    MildomIE,
    MildomVodIE,
    MildomUserVodIE,
)
from .minds import (
    MindsIE,
    MindsChannelIE,
    MindsGroupIE,
)
from .ministrygrid import MinistryGridIE
from .minoto import MinotoIE
from .miomio import MioMioIE
from .mirrativ import (
    MirrativIE,
    MirrativUserIE,
)
from .mit import TechTVMITIE, OCWMITIE
from .mitele import MiTeleIE
from .mixcloud import (
    MixcloudIE,
    MixcloudUserIE,
    MixcloudPlaylistIE,
)
from .mlb import (
    MLBIE,
    MLBVideoIE,
)
from .mnet import MnetIE
from .moevideo import MoeVideoIE
from .mofosex import (
    MofosexIE,
    MofosexEmbedIE,
)
from .mojvideo import MojvideoIE
from .morningstar import MorningstarIE
from .motherless import (
    MotherlessIE,
    MotherlessGroupIE
)
from .motorsport import MotorsportIE
from .movieclips import MovieClipsIE
from .moviezine import MoviezineIE
from .movingimage import MovingImageIE
from .msn import MSNIE
from .mtv import (
    MTVIE,
    MTVVideoIE,
    MTVServicesEmbeddedIE,
    MTVDEIE,
    MTVJapanIE,
    MTVItaliaIE,
    MTVItaliaProgrammaIE,
)
from .muenchentv import MuenchenTVIE
from .mwave import MwaveIE, MwaveMeetGreetIE
from .mxplayer import (
    MxplayerIE,
    MxplayerShowIE,
)
from .mychannels import MyChannelsIE
from .myspace import MySpaceIE, MySpaceAlbumIE
from .myspass import MySpassIE
from .myvi import (
    MyviIE,
    MyviEmbedIE,
)
from .myvideoge import MyVideoGeIE
from .myvidster import MyVidsterIE
from .nationalgeographic import (
    NationalGeographicVideoIE,
    NationalGeographicTVIE,
)
from .naver import (
    NaverIE,
    NaverLiveIE,
)
from .nba import (
    NBAWatchEmbedIE,
    NBAWatchIE,
    NBAWatchCollectionIE,
    NBAEmbedIE,
    NBAIE,
    NBAChannelIE,
)
from .nbc import (
    NBCIE,
    NBCNewsIE,
    NBCOlympicsIE,
    NBCOlympicsStreamIE,
    NBCSportsIE,
    NBCSportsStreamIE,
    NBCSportsVPlayerIE,
)
from .ndr import (
    NDRIE,
    NJoyIE,
    NDREmbedBaseIE,
    NDREmbedIE,
    NJoyEmbedIE,
)
from .ndtv import NDTVIE
from .nebula import NebulaIE
from .nerdcubed import NerdCubedFeedIE
from .netzkino import NetzkinoIE
from .neteasemusic import (
    NetEaseMusicIE,
    NetEaseMusicAlbumIE,
    NetEaseMusicSingerIE,
    NetEaseMusicListIE,
    NetEaseMusicMvIE,
    NetEaseMusicProgramIE,
    NetEaseMusicDjRadioIE,
)
from .newgrounds import (
    NewgroundsIE,
    NewgroundsPlaylistIE,
)
from .newstube import NewstubeIE
from .nextmedia import (
    NextMediaIE,
    NextMediaActionNewsIE,
    AppleDailyIE,
    NextTVIE,
)
from .nexx import (
    NexxIE,
    NexxEmbedIE,
)
from .nfhsnetwork import NFHSNetworkIE
from .nfl import (
    NFLIE,
    NFLArticleIE,
)
from .nhk import (
    NhkVodIE,
    NhkVodProgramIE,
)
from .nhl import NHLIE
from .nick import (
    NickIE,
    NickBrIE,
    NickDeIE,
    NickNightIE,
    NickRuIE,
)

from .niconico import (
    NiconicoIE,
    NiconicoPlaylistIE,
    NiconicoUserIE,
    NicovideoSearchDateIE,
    NicovideoSearchIE,
    NicovideoSearchURLIE,
)
from .ninecninemedia import NineCNineMediaIE
from .ninegag import NineGagIE
from .ninenow import NineNowIE
from .nintendo import NintendoIE
from .nitter import NitterIE
from .njpwworld import NJPWWorldIE
from .nobelprize import NobelPrizeIE
from .nonktube import NonkTubeIE
from .noovo import NoovoIE
from .normalboots import NormalbootsIE
from .nosvideo import NosVideoIE
from .nova import (
    NovaEmbedIE,
    NovaIE,
)
from .nowness import (
    NownessIE,
    NownessPlaylistIE,
    NownessSeriesIE,
)
from .noz import NozIE
from .npo import (
    AndereTijdenIE,
    NPOIE,
    NPOLiveIE,
    NPORadioIE,
    NPORadioFragmentIE,
    SchoolTVIE,
    HetKlokhuisIE,
    VPROIE,
    WNLIE,
)
from .npr import NprIE
from .nrk import (
    NRKIE,
    NRKPlaylistIE,
    NRKSkoleIE,
    NRKTVIE,
    NRKTVDirekteIE,
    NRKRadioPodkastIE,
    NRKTVEpisodeIE,
    NRKTVEpisodesIE,
    NRKTVSeasonIE,
    NRKTVSeriesIE,
)
from .nrl import NRLTVIE
from .ntvcojp import NTVCoJpCUIE
from .ntvde import NTVDeIE
from .ntvru import NTVRuIE
from .nytimes import (
    NYTimesIE,
    NYTimesArticleIE,
    NYTimesCookingIE,
)
from .nuvid import NuvidIE
from .nzz import NZZIE
from .odatv import OdaTVIE
from .odnoklassniki import OdnoklassnikiIE
from .oktoberfesttv import OktoberfestTVIE
from .ondemandkorea import OnDemandKoreaIE
from .onet import (
    OnetIE,
    OnetChannelIE,
    OnetMVPIE,
    OnetPlIE,
)
from .onionstudios import OnionStudiosIE
from .ooyala import (
    OoyalaIE,
    OoyalaExternalIE,
)
from .openrec import (
    OpenRecIE,
    OpenRecCaptureIE,
)
from .ora import OraTVIE
from .orf import (
    ORFTVthekIE,
    ORFFM4IE,
    ORFFM4StoryIE,
    ORFOE1IE,
    ORFOE3IE,
    ORFNOEIE,
    ORFWIEIE,
    ORFBGLIE,
    ORFOOEIE,
    ORFSTMIE,
    ORFKTNIE,
    ORFSBGIE,
    ORFTIRIE,
    ORFVBGIE,
    ORFIPTVIE,
)
from .outsidetv import OutsideTVIE
from .packtpub import (
    PacktPubIE,
    PacktPubCourseIE,
)
from .palcomp3 import (
    PalcoMP3IE,
    PalcoMP3ArtistIE,
    PalcoMP3VideoIE,
)
from .pandoratv import PandoraTVIE
from .paramountplus import (
    ParamountPlusIE,
    ParamountPlusSeriesIE,
)
from .parliamentliveuk import ParliamentLiveUKIE
from .parlview import ParlviewIE
from .patreon import (
    PatreonIE,
    PatreonUserIE
)
from .pbs import PBSIE
from .pearvideo import PearVideoIE
from .peertube import PeerTubeIE
from .peloton import (
    PelotonIE,
    PelotonLiveIE
)
from .people import PeopleIE
from .performgroup import PerformGroupIE
from .periscope import (
    PeriscopeIE,
    PeriscopeUserIE,
)
from .philharmoniedeparis import PhilharmonieDeParisIE
from .phoenix import PhoenixIE
from .photobucket import PhotobucketIE
from .picarto import (
    PicartoIE,
    PicartoVodIE,
)
from .piksel import PikselIE
from .pinkbike import PinkbikeIE
from .pinterest import (
    PinterestIE,
    PinterestCollectionIE,
)
from .pladform import PladformIE
from .platzi import (
    PlatziIE,
    PlatziCourseIE,
)
from .playfm import PlayFMIE
from .playplustv import PlayPlusTVIE
from .plays import PlaysTVIE
from .playstuff import PlayStuffIE
from .playtvak import PlaytvakIE
from .playvid import PlayvidIE
from .playwire import PlaywireIE
from .plutotv import PlutoTVIE
from .pluralsight import (
    PluralsightIE,
    PluralsightCourseIE,
)
from .podomatic import PodomaticIE
from .pokemon import (
    PokemonIE,
    PokemonWatchIE,
)
from .polskieradio import (
    PolskieRadioIE,
    PolskieRadioCategoryIE,
)
from .popcorntimes import PopcorntimesIE
from .popcorntv import PopcornTVIE
from .porn91 import Porn91IE
from .porncom import PornComIE
from .pornflip import PornFlipIE
from .pornhd import PornHdIE
from .pornhub import (
    PornHubIE,
    PornHubUserIE,
    PornHubPlaylistIE,
    PornHubPagedVideoListIE,
    PornHubUserVideosUploadIE,
)
from .pornotube import PornotubeIE
from .pornovoisines import PornoVoisinesIE
from .pornoxo import PornoXOIE
from .puhutv import (
    PuhuTVIE,
    PuhuTVSerieIE,
)
from .presstv import PressTVIE
from .projectveritas import ProjectVeritasIE
from .prosiebensat1 import ProSiebenSat1IE
from .puls4 import Puls4IE
from .pyvideo import PyvideoIE
from .qqmusic import (
    QQMusicIE,
    QQMusicSingerIE,
    QQMusicAlbumIE,
    QQMusicToplistIE,
    QQMusicPlaylistIE,
)
from .r7 import (
    R7IE,
    R7ArticleIE,
)
from .radiko import RadikoIE, RadikoRadioIE
from .radiocanada import (
    RadioCanadaIE,
    RadioCanadaAudioVideoIE,
)
from .radiode import RadioDeIE
from .radiojavan import RadioJavanIE
from .radiobremen import RadioBremenIE
from .radiofrance import RadioFranceIE
from .rai import (
    RaiPlayIE,
    RaiPlayLiveIE,
    RaiPlayPlaylistIE,
    RaiIE,
)
from .raywenderlich import (
    RayWenderlichIE,
    RayWenderlichCourseIE,
)
from .rbmaradio import RBMARadioIE
from .rcs import (
    RCSIE,
    RCSEmbedsIE,
    RCSVariousIE,
)
from .rcti import (
    RCTIPlusIE,
    RCTIPlusSeriesIE,
    RCTIPlusTVIE,
)
from .rds import RDSIE
from .redbulltv import (
    RedBullTVIE,
    RedBullEmbedIE,
    RedBullTVRrnContentIE,
    RedBullIE,
)
from .reddit import (
    RedditIE,
    RedditRIE,
)
from .redtube import RedTubeIE
from .regiotv import RegioTVIE
from .rentv import (
    RENTVIE,
    RENTVArticleIE,
)
from .restudy import RestudyIE
from .reuters import ReutersIE
from .reverbnation import ReverbNationIE
from .rice import RICEIE
from .rmcdecouverte import RMCDecouverteIE
from .ro220 import Ro220IE
from .rockstargames import RockstarGamesIE
from .roosterteeth import RoosterTeethIE
from .rottentomatoes import RottenTomatoesIE
from .roxwel import RoxwelIE
from .rozhlas import RozhlasIE
from .rtbf import RTBFIE
from .rte import RteIE, RteRadioIE
from .rtlnl import RtlNlIE
from .rtl2 import (
    RTL2IE,
    RTL2YouIE,
    RTL2YouSeriesIE,
)
from .rtp import RTPIE
from .rts import RTSIE
from .rtve import RTVEALaCartaIE, RTVELiveIE, RTVEInfantilIE, RTVELiveIE, RTVETelevisionIE
from .rtvnh import RTVNHIE
from .rtvs import RTVSIE
from .ruhd import RUHDIE
from .rumble import RumbleEmbedIE
from .rutube import (
    RutubeIE,
    RutubeChannelIE,
    RutubeEmbedIE,
    RutubeMovieIE,
    RutubePersonIE,
    RutubePlaylistIE,
)
from .rutv import RUTVIE
from .ruutu import RuutuIE
from .ruv import RuvIE
from .safari import (
    SafariIE,
    SafariApiIE,
    SafariCourseIE,
)
from .saitosan import SaitosanIE
from .samplefocus import SampleFocusIE
from .sapo import SapoIE
from .savefrom import SaveFromIE
from .sbs import SBSIE
from .screencast import ScreencastIE
from .screencastomatic import ScreencastOMaticIE
from .scrippsnetworks import (
    ScrippsNetworksWatchIE,
    ScrippsNetworksIE,
)
from .scte import (
    SCTEIE,
    SCTECourseIE,
)
from .seeker import SeekerIE
from .senateisvp import SenateISVPIE
from .sendtonews import SendtoNewsIE
from .servus import ServusIE
from .sevenplus import SevenPlusIE
from .sexu import SexuIE
from .seznamzpravy import (
    SeznamZpravyIE,
    SeznamZpravyArticleIE,
)
from .shahid import (
    ShahidIE,
    ShahidShowIE,
)
from .shared import (
    SharedIE,
    VivoIE,
)
from .shemaroome import ShemarooMeIE
from .showroomlive import ShowRoomLiveIE
from .simplecast import (
    SimplecastIE,
    SimplecastEpisodeIE,
    SimplecastPodcastIE,
)
from .sina import SinaIE
from .sixplay import SixPlayIE
from .skyit import (
    SkyItPlayerIE,
    SkyItVideoIE,
    SkyItVideoLiveIE,
    SkyItIE,
    SkyItAcademyIE,
    SkyItArteIE,
    CieloTVItIE,
    TV8ItIE,
)
from .skylinewebcams import SkylineWebcamsIE
from .skynewsarabia import (
    SkyNewsArabiaIE,
    SkyNewsArabiaArticleIE,
)
from .sky import (
    SkyNewsIE,
    SkySportsIE,
    SkySportsNewsIE,
)
from .slideshare import SlideshareIE
from .slideslive import SlidesLiveIE
from .slutload import SlutloadIE
from .snotr import SnotrIE
from .sohu import SohuIE
from .sonyliv import (
    SonyLIVIE,
    SonyLIVSeriesIE,
)
from .soundcloud import (
    SoundcloudEmbedIE,
    SoundcloudIE,
    SoundcloudSetIE,
    SoundcloudUserIE,
    SoundcloudTrackStationIE,
    SoundcloudPlaylistIE,
    SoundcloudSearchIE,
)
from .soundgasm import (
    SoundgasmIE,
    SoundgasmProfileIE
)
from .southpark import (
    SouthParkIE,
    SouthParkDeIE,
    SouthParkDkIE,
    SouthParkEsIE,
    SouthParkNlIE
)
from .sovietscloset import (
    SovietsClosetIE,
    SovietsClosetPlaylistIE
)
from .spankbang import (
    SpankBangIE,
    SpankBangPlaylistIE,
)
from .spankwire import SpankwireIE
from .spiegel import SpiegelIE
from .spike import (
    BellatorIE,
    ParamountNetworkIE,
)
from .stitcher import (
    StitcherIE,
    StitcherShowIE,
)
from .sport5 import Sport5IE
from .sportbox import SportBoxIE
from .sportdeutschland import SportDeutschlandIE
from .spotify import (
    SpotifyIE,
    SpotifyShowIE,
)
from .spreaker import (
    SpreakerIE,
    SpreakerPageIE,
    SpreakerShowIE,
    SpreakerShowPageIE,
)
from .springboardplatform import SpringboardPlatformIE
from .sprout import SproutIE
from .srgssr import (
    SRGSSRIE,
    SRGSSRPlayIE,
)
from .srmediathek import SRMediathekIE
from .stanfordoc import StanfordOpenClassroomIE
from .startv import StarTVIE
from .steam import SteamIE
from .storyfire import (
    StoryFireIE,
    StoryFireUserIE,
    StoryFireSeriesIE,
)
from .streamable import StreamableIE
from .streamcloud import StreamcloudIE
from .streamcz import StreamCZIE
from .streetvoice import StreetVoiceIE
from .stretchinternet import StretchInternetIE
from .stv import STVPlayerIE
from .sunporno import SunPornoIE
from .sverigesradio import (
    SverigesRadioEpisodeIE,
    SverigesRadioPublicationIE,
)
from .svt import (
    SVTIE,
    SVTPageIE,
    SVTPlayIE,
    SVTSeriesIE,
)
from .swrmediathek import SWRMediathekIE
from .syfy import SyfyIE
from .sztvhu import SztvHuIE
from .tagesschau import (
    TagesschauPlayerIE,
    TagesschauIE,
)
from .tass import TassIE
from .tbs import TBSIE
from .tdslifeway import TDSLifewayIE
from .teachable import (
    TeachableIE,
    TeachableCourseIE,
)
from .teachertube import (
    TeacherTubeIE,
    TeacherTubeUserIE,
)
from .teachingchannel import TeachingChannelIE
from .teamcoco import TeamcocoIE
from .teamtreehouse import TeamTreeHouseIE
from .techtalks import TechTalksIE
from .ted import TEDIE
from .tele5 import Tele5IE
from .tele13 import Tele13IE
from .telebruxelles import TeleBruxellesIE
from .telecinco import TelecincoIE
from .telegraaf import TelegraafIE
from .telemb import TeleMBIE
from .telemundo import TelemundoIE
from .telequebec import (
    TeleQuebecIE,
    TeleQuebecSquatIE,
    TeleQuebecEmissionIE,
    TeleQuebecLiveIE,
    TeleQuebecVideoIE,
)
from .teletask import TeleTaskIE
from .telewebion import TelewebionIE
from .tennistv import TennisTVIE
from .tenplay import TenPlayIE
from .testurl import TestURLIE
from .tf1 import TF1IE
from .tfo import TFOIE
from .theintercept import TheInterceptIE
from .theplatform import (
    ThePlatformIE,
    ThePlatformFeedIE,
)
from .thescene import TheSceneIE
from .thestar import TheStarIE
from .thesun import TheSunIE
from .theweatherchannel import TheWeatherChannelIE
from .thisamericanlife import ThisAmericanLifeIE
from .thisav import ThisAVIE
from .thisoldhouse import ThisOldHouseIE
from .threeqsdn import ThreeQSDNIE
from .tiktok import (
    TikTokIE,
    TikTokUserIE,
)
from .tinypic import TinyPicIE
from .tmz import TMZIE
from .tnaflix import (
    TNAFlixNetworkEmbedIE,
    TNAFlixIE,
    EMPFlixIE,
    MovieFapIE,
)
from .toggle import (
    ToggleIE,
    MeWatchIE,
)
from .tokentube import (
    TokentubeIE,
    TokentubeChannelIE
)
from .tonline import TOnlineIE
from .toongoggles import ToonGogglesIE
from .toutv import TouTvIE
from .toypics import ToypicsUserIE, ToypicsIE
from .traileraddict import TrailerAddictIE
from .trilulilu import TriluliluIE
from .trovo import (
    TrovoIE,
    TrovoVodIE,
)
from .trunews import TruNewsIE
from .trutv import TruTVIE
from .tube8 import Tube8IE
from .tubitv import (
    TubiTvIE,
    TubiTvShowIE,
)
from .tumblr import TumblrIE
from .tunein import (
    TuneInClipIE,
    TuneInStationIE,
    TuneInProgramIE,
    TuneInTopicIE,
    TuneInShortenerIE,
)
from .tunepk import TunePkIE
from .turbo import TurboIE
from .tv2 import (
    TV2IE,
    TV2ArticleIE,
    KatsomoIE,
    MTVUutisetArticleIE,
)
from .tv2dk import (
    TV2DKIE,
    TV2DKBornholmPlayIE,
)
from .tv2hu import (
    TV2HuIE,
    TV2HuSeriesIE,
)
from .tv4 import TV4IE
from .tv5mondeplus import TV5MondePlusIE
from .tv5unis import (
    TV5UnisVideoIE,
    TV5UnisIE,
)
from .tva import (
    TVAIE,
    QubIE,
)
from .tvanouvelles import (
    TVANouvellesIE,
    TVANouvellesArticleIE,
)
from .tvc import (
    TVCIE,
    TVCArticleIE,
)
from .tver import TVerIE
from .tvigle import TvigleIE
from .tvland import TVLandIE
from .tvn24 import TVN24IE
from .tvnet import TVNetIE
from .tvnoe import TVNoeIE
from .tvnow import (
    TVNowIE,
    TVNowFilmIE,
    TVNowNewIE,
    TVNowSeasonIE,
    TVNowAnnualIE,
    TVNowShowIE,
)
from .tvp import (
    TVPEmbedIE,
    TVPIE,
    TVPWebsiteIE,
)
from .tvplay import (
    TVPlayIE,
    ViafreeIE,
    TVPlayHomeIE,
)
from .tvplayer import TVPlayerIE
from .tweakers import TweakersIE
from .twentyfourvideo import TwentyFourVideoIE
from .twentymin import TwentyMinutenIE
from .twentythreevideo import TwentyThreeVideoIE
from .twitcasting import (
    TwitCastingIE,
    TwitCastingLiveIE,
    TwitCastingUserIE,
)
from .twitch import (
    TwitchVodIE,
    TwitchCollectionIE,
    TwitchVideosIE,
    TwitchVideosClipsIE,
    TwitchVideosCollectionsIE,
    TwitchStreamIE,
    TwitchClipsIE,
)
from .twitter import (
    TwitterCardIE,
    TwitterIE,
    TwitterAmplifyIE,
    TwitterBroadcastIE,
    TwitterShortenerIE,
)
from .udemy import (
    UdemyIE,
    UdemyCourseIE
)
from .udn import UDNEmbedIE
from .ufctv import (
    UFCTVIE,
    UFCArabiaIE,
)
from .ukcolumn import UkColumnIE
from .uktvplay import UKTVPlayIE
from .digiteka import DigitekaIE
from .dlive import (
    DLiveVODIE,
    DLiveStreamIE,
)
from .umg import UMGDeIE
from .unistra import UnistraIE
from .unity import UnityIE
from .uol import UOLIE
from .uplynk import (
    UplynkIE,
    UplynkPreplayIE,
)
from .urort import UrortIE
from .urplay import URPlayIE
from .usanetwork import USANetworkIE
from .usatoday import USATodayIE
from .ustream import UstreamIE, UstreamChannelIE
from .ustudio import (
    UstudioIE,
    UstudioEmbedIE,
)
from .utreon import UtreonIE
from .varzesh3 import Varzesh3IE
from .vbox7 import Vbox7IE
from .veehd import VeeHDIE
from .veoh import VeohIE
from .vesti import VestiIE
from .vevo import (
    VevoIE,
    VevoPlaylistIE,
)
from .vgtv import (
    BTArticleIE,
    BTVestlendingenIE,
    VGTVIE,
)
from .vh1 import VH1IE
from .vice import (
    ViceIE,
    ViceArticleIE,
    ViceShowIE,
)
from .vidbit import VidbitIE
from .viddler import ViddlerIE
from .videa import VideaIE
from .videodetective import VideoDetectiveIE
from .videofyme import VideofyMeIE
from .videomore import (
    VideomoreIE,
    VideomoreVideoIE,
    VideomoreSeasonIE,
)
from .videopress import VideoPressIE
from .vidio import (
    VidioIE,
    VidioPremierIE,
    VidioLiveIE
)
from .vidlii import VidLiiIE
from .vidme import (
    VidmeIE,
    VidmeUserIE,
    VidmeUserLikesIE,
)
from .vier import VierIE, VierVideosIE
from .viewlift import (
    ViewLiftIE,
    ViewLiftEmbedIE,
)
from .viidea import ViideaIE
from .vimeo import (
    VimeoIE,
    VimeoAlbumIE,
    VimeoChannelIE,
    VimeoGroupsIE,
    VimeoLikesIE,
    VimeoOndemandIE,
    VimeoReviewIE,
    VimeoUserIE,
    VimeoWatchLaterIE,
    VHXEmbedIE,
)
from .vimple import VimpleIE
from .vine import (
    VineIE,
    VineUserIE,
)
from .viki import (
    VikiIE,
    VikiChannelIE,
)
from .viqeo import ViqeoIE
from .viu import (
    ViuIE,
    ViuPlaylistIE,
    ViuOTTIE,
)
from .vk import (
    VKIE,
    VKUserVideosIE,
    VKWallPostIE,
)
from .vlive import (
    VLiveIE,
    VLivePostIE,
    VLiveChannelIE,
)
from .vodlocker import VodlockerIE
from .vodpl import VODPlIE
from .vodplatform import VODPlatformIE
from .voicerepublic import VoiceRepublicIE
from .voicy import (
    VoicyIE,
    VoicyChannelIE,
)
from .voot import (
    VootIE,
    VootSeriesIE,
)
from .voxmedia import (
    VoxMediaVolumeIE,
    VoxMediaIE,
)
from .vrt import VRTIE
from .vrak import VrakIE
from .vrv import (
    VRVIE,
    VRVSeriesIE,
)
from .vshare import VShareIE
from .vtm import VTMIE
from .medialaan import MedialaanIE
from .vube import VubeIE
from .vuclip import VuClipIE
from .vvvvid import (
    VVVVIDIE,
    VVVVIDShowIE,
)
from .vyborymos import VyboryMosIE
from .vzaar import VzaarIE
from .wakanim import WakanimIE
from .walla import WallaIE
from .washingtonpost import (
    WashingtonPostIE,
    WashingtonPostArticleIE,
)
from .wat import WatIE
from .watchbox import WatchBoxIE
from .watchindianporn import WatchIndianPornIE
from .wdr import (
    WDRIE,
    WDRPageIE,
    WDRElefantIE,
    WDRMobileIE,
)
from .webcaster import (
    WebcasterIE,
    WebcasterFeedIE,
)
from .webofstories import (
    WebOfStoriesIE,
    WebOfStoriesPlaylistIE,
)
from .weibo import (
    WeiboIE,
    WeiboMobileIE
)
from .weiqitv import WeiqiTVIE
from .wimtv import WimTVIE
from .whowatch import WhoWatchIE
from .wistia import (
    WistiaIE,
    WistiaPlaylistIE,
)
from .worldstarhiphop import WorldStarHipHopIE
from .wsj import (
    WSJIE,
    WSJArticleIE,
)
from .wwe import WWEIE
from .xbef import XBefIE
from .xboxclips import XboxClipsIE
from .xfileshare import XFileShareIE
from .xhamster import (
    XHamsterIE,
    XHamsterEmbedIE,
    XHamsterUserIE,
)
from .xiami import (
    XiamiSongIE,
    XiamiAlbumIE,
    XiamiArtistIE,
    XiamiCollectionIE
)
from .ximalaya import (
    XimalayaIE,
    XimalayaAlbumIE
)
from .xminus import XMinusIE
from .xnxx import XNXXIE
from .xstream import XstreamIE
from .xtube import XTubeUserIE, XTubeIE
from .xuite import XuiteIE
from .xvideos import XVideosIE
from .xxxymovies import XXXYMoviesIE
from .yahoo import (
    YahooIE,
    YahooSearchIE,
    YahooGyaOPlayerIE,
    YahooGyaOIE,
    YahooJapanNewsIE,
)
from .yandexdisk import YandexDiskIE
from .yandexmusic import (
    YandexMusicTrackIE,
    YandexMusicAlbumIE,
    YandexMusicPlaylistIE,
    YandexMusicArtistTracksIE,
    YandexMusicArtistAlbumsIE,
)
from .yandexvideo import YandexVideoIE
from .yapfiles import YapFilesIE
from .yesjapan import YesJapanIE
from .yinyuetai import YinYueTaiIE
from .ynet import YnetIE
from .youjizz import YouJizzIE
from .youku import (
    YoukuIE,
    YoukuShowIE,
)
from .younow import (
    YouNowLiveIE,
    YouNowChannelIE,
    YouNowMomentIE,
)
from .youporn import YouPornIE
from .yourporn import YourPornIE
from .yourupload import YourUploadIE
from .youtube import (
    YoutubeIE,
    YoutubeFavouritesIE,
    YoutubeHistoryIE,
    YoutubeTabIE,
    YoutubePlaylistIE,
    YoutubeRecommendedIE,
    YoutubeSearchDateIE,
    YoutubeSearchIE,
    YoutubeSearchURLIE,
    YoutubeSubscriptionsIE,
    YoutubeTruncatedIDIE,
    YoutubeTruncatedURLIE,
    YoutubeYtBeIE,
    YoutubeYtUserIE,
    YoutubeWatchLaterIE,
)
from .zapiks import ZapiksIE
from .zattoo import (
    BBVTVIE,
    EinsUndEinsTVIE,
    EWETVIE,
    GlattvisionTVIE,
    MNetTVIE,
    MyVisionTVIE,
    NetPlusIE,
    OsnatelTVIE,
    QuantumTVIE,
    QuicklineIE,
    QuicklineLiveIE,
    SaltTVIE,
    SAKTVIE,
    VTXTVIE,
    WalyTVIE,
    ZattooIE,
    ZattooLiveIE,
)
from .zdf import ZDFIE, ZDFChannelIE
from .zee5 import (
    Zee5IE,
    Zee5SeriesIE,
)
from .zhihu import ZhihuIE
from .zingmp3 import (
    ZingMp3IE,
    ZingMp3AlbumIE,
)
from .zoom import ZoomIE
from .zype import ZypeIE


from dagstermill.examples.repository import notebook_repo

from dagster import RepositoryDefinition

def test_dagstermill_repo():
    assert isinstance(notebook_repo, RepositoryDefinition)


# -*- coding: utf-8 -*-

"""
file: module_graph_copy_test.py

Unit tests for Graph copy related methods
"""

import copy

from unittest_baseclass import UnittestPythonCompatibility

from graphit import Graph

class TestGraphCopy(UnittestPythonCompatibility):
    """
    Test Graph copy and deepcopy methods
    """

    def setUp(self):
        """
        Build default graph with nodes, edges and attributes
        """

        self.graph = Graph()
        self.graph.add_nodes([('g', {'weight': 1.0}), ('r', {'weight': 1.5}), ('a', {'weight': 2.0}),
                              ('p', {'weight': 2.5}), ('h', {'weight': 3.0})])
        self.graph.add_edges([(1, 2), (2, 3), (3, 4), (3, 5), (4, 5)], isedge=True)

    def tearDown(self):
        """
        Test copied state
        Testing equality in node, edge and adjacency data stores is based on
        the internal '_storage' object and not so much the storage object
        itself which is often just a wrapper.
        """

        # Main Graph object is new
        self.assertTrue(id(self.copied) != id(self.graph))

        if self.shallow:

            # Internal node and edge stores point to parent.
            self.assertEqual(id(self.copied.nodes._storage), id(self.graph.nodes._storage))
            self.assertEqual(id(self.copied.edges._storage), id(self.graph.edges._storage))

            # ORM and origin objects point to parent
            self.assertEqual(id(self.copied.orm), id(self.graph.orm))
            self.assertEqual(id(self.copied.origin), id(self.graph.origin))

        else:

            # Internal node and edge stores point to parent.
            self.assertNotEqual(id(self.copied.nodes._storage), id(self.graph.nodes._storage))
            self.assertNotEqual(id(self.copied.edges._storage), id(self.graph.edges._storage))

            # ORM and origin objects point to parent
            self.assertNotEqual(id(self.copied.orm), id(self.graph.orm))
            self.assertNotEqual(id(self.copied.origin), id(self.graph.origin))

    def test_graph_copy_shallow(self):
        """
        Test making a shallow copy of a graph. This essentially copies the
        Graph object while linking tot the data store in the parent Graph
        """

        self.shallow = True
        self.copied = self.graph.copy(deep=False)

    def test_graph_copy_deep(self):
        """
        Test making a deep copy of a graph (default) copying everything
        """

        self.shallow = False
        self.copied = self.graph.copy()

    def test_graph_buildin_copy_shallow(self):
        """
        Test making a shallow copy of a graph using the 'copy' method of the
        copy class. This calls the Graph.copy method
        """

        self.shallow = True
        self.copied = copy.copy(self.graph)

    def test_graph_buildin_copy_deep(self):
        """
        Test making a deep copy of a graph using the 'deepcopy' method of the
        copy class. This calls the Graph.copy method
        """

        self.shallow = False
        self.copied = copy.deepcopy(self.graph)

    def test_graph_buildin_copy_deep_view(self):
        """
        Test copying subgraphs either with the set 'view' only or the full
        origin graph (full graph)
        """

        # Regular copy
        self.shallow = False
        self.copied = copy.deepcopy(self.graph)

        # Build subgraph, same origin
        view = self.graph.getnodes([3,4,5])
        self.assertEqual(id(view.origin), id(self.graph.origin))

        # Deep copy with or without view, different origin
        copy_view = view.copy(deep=True, copy_view=False)
        copy_full = view.copy(deep=True, copy_view=True)
        self.assertNotEqual(id(copy_view.origin), id(self.graph.origin))
        self.assertNotEqual(id(copy_full.origin), id(self.graph.origin))

        # Subgraph 'view' should be identical to the original
        # regardless the copy mode
        self.assertEqual(copy_view.nodes.keys(), view.nodes.keys())
        self.assertEqual(copy_view.edges.keys(), view.edges.keys())
        self.assertEqual(copy_view.adjacency.keys(), view.adjacency.keys())
        self.assertEqual(copy_full.nodes.keys(), view.nodes.keys())
        self.assertEqual(copy_full.edges.keys(), view.edges.keys())
        self.assertEqual(copy_full.adjacency.keys(), view.adjacency.keys())

        # The view copy origin should either be identical to the view
        # (copy_view = True) or to the full graph (copy_view = False)
        self.assertEqual(list(copy_view.nodes._storage.keys()), list(view.nodes.keys()))
        self.assertEqual(list(copy_full.nodes._storage.keys()), list(view.origin.nodes.keys()))

        # The copy_full has its origin equals self and thus copy_full.origin.nodes
        # equals copy_full.nodes. However, the view is also set which means that
        # by default the full graph is not accessible without resetting it
        copy_full.nodes.reset_view()
        self.assertEqual(copy_full.nodes.keys(), self.graph.nodes.keys())


"""
## SCRIPT HEADER ##

Created By   : Muhammad Fredo
Email        : muhammadfredo@gmail.com
Start Date   : 03 Nov 2020
Info         :

alternative_callback_data: header data
  "id": (callback id)
    "event_name": "after_open"
    "callback_tag": fr_maya

maya_event_callbacks:
  after_open:
    event_id: event_id,
    add_callback: om callback function
  before_open:
    event_id: event_id,
    add_callback: om callback function
"""
import copy
import inspect
import re

import maya.OpenMaya as om
# TODO: update to api 2.0 ??

from FrMaya import utility as util

class MyCallbackManager(object):
    __metaclass__ = util.MetaSingleton

    @staticmethod
    def get_maya_event_callback():
        """
        Return dictionary data of Maya events callback.

        after_open:
            event_id: event_id,

            add_callback: open Maya callback function.
        before_open:
            event_id: event_id,

            add_callback: open Maya callback function.
        :rtype: dict
        """
        # example regex subs -> re.sub(r"(\w)([A-Z])", r"\1 \2", "WordWordWord")
        callback_events = {}
        re_pattern = re.compile(r'(?<=\w)([A-Z])')
        for event_name, event_id in inspect.getmembers(om.MSceneMessage):
            if event_name.startswith('k') and not event_name.endswith('check'):
                if not callback_events.get(event_name):
                    key_name = re_pattern.sub(r'_\1', event_name[1:])
                    callback_events[key_name.lower()] = {
                        'event_id': event_id,
                        'add_callback': om.MSceneMessage.addCallback,
                    }

        return callback_events

    def __init__(self):
        """Class to manage callback for FrMaya system."""
        print 'initialize callback manager'
        self._maya_event_callback = {}
        self._registered_callback = {}

        self._maya_event_callback = copy.deepcopy(self.get_maya_event_callback())

        assert len(self._maya_event_callback) > 0, ''

    def _group_registered_callbacks(self):
        """
        Return registered callbacks based on events or tags callback.

        events:
            event_name: [callback function name, ..],

        tags:
            callback_tag: [callback function name, ..],

        :rtype: dict
        """
        result_data = {'events': {}, 'tags': {}}
        for cb_fn_name, cb_data in self._registered_callback.items():
            for each in result_data:
                if each == 'events':
                    event_or_tag = cb_data['event_name']
                elif each == 'tags':
                    event_or_tag = cb_data['callback_tag']
                else:
                    return None

                if result_data[each].get(event_or_tag):
                    result_data[each][event_or_tag].append(cb_fn_name)
                else:
                    result_data[each][event_or_tag] = [cb_fn_name]
        return result_data

    def add_callback(self, event_name, callback_tag, func):
        """
        Return True if it success add callback to callback manager, False otherwise.

        :arg event_name: Maya event nice name.
        :type event_name: str
        :arg callback_tag: A tag to group callback in callback manager.
        :type callback_tag: str
        :arg func: Python function.
        :rtype: bool
        """
        my_event_cb = self._maya_event_callback.get(event_name)

        if my_event_cb:
            callback_id = my_event_cb['add_callback'](my_event_cb['event_id'], func)

            self._registered_callback[func.__module__] = {
                'event_name': event_name,
                'callback_tag': callback_tag,
                'callback_id': callback_id
            }

            return True
        else:
            return False

    def remove_callback(self, event_name = '', callback_tag = ''):
        """
        Remove callback based on specified keyword argument.
        If both keyword specified, it will performed both action.

        :key event_name: Maya event name callback which want to removed.
        :type event_name: str
        :key callback_tag: Callback tag which want to removed.
        :type callback_tag: str
        """
        callback_collection = self._group_registered_callbacks()

        cb_id_array = om.MCallbackIdArray()
        cb_fn_name_list = []
        if event_name:
            cb_fn_name_list.extend(callback_collection['events'].get(event_name, []))
        if callback_tag:
            cb_fn_name_list.extend(callback_collection['tags'].get(callback_tag, []))

        for cb_fn_name in cb_fn_name_list:
            cb_id_array.append(self._registered_callback[cb_fn_name]['callback_id'])

        if cb_id_array:
            om.MMessage.removeCallbacks(cb_id_array)

    def show_registered_callback(self, event_name = '', callback_tag = ''):
        """
        Return registered callback based on specified keyword,
        if both keyword did not specified, it will return both group data (event name and tag).

        :key event_name: Maya event name callback which callback group want to retrieved.
        :type event_name: str
        :key callback_tag: Callback tag which callback group want to retrieved.
        :type callback_tag: str
        :rtype: dict or list
        """
        result = self._group_registered_callbacks()

        if event_name:
            return result['events'].get(event_name, [])
        elif callback_tag:
            return result['tags'].get(callback_tag, [])
        else:
            return copy.deepcopy(result)

    def show_maya_event_name(self):
        """
        Return list of Maya event nice name.

        :rtype: list of str
        """
        return self._maya_event_callback.keys()


from typing import Sequence, Union, Optional, Callable, Dict, Any, Tuple
import torch

from ignite.engine.engine import Engine
from ignite.engine.events import State, Events, EventEnum, CallableEventWithFilter
from ignite.utils import convert_tensor
from ignite.metrics import Metric

__all__ = [
    "State",
    "create_supervised_trainer",
    "create_supervised_evaluator",
    "Engine",
    "Events",
    "EventEnum",
    "CallableEventWithFilter",
]

def _prepare_batch(
    batch: Sequence[torch.Tensor], device: Optional[Union[str, torch.device]] = None, non_blocking: bool = False
):
    """Prepare batch for training: pass to a device with options.

    """
    x, y = batch
    return (
        convert_tensor(x, device=device, non_blocking=non_blocking),
        convert_tensor(y, device=device, non_blocking=non_blocking),
    )

def create_supervised_trainer(
    model: torch.nn.Module,
    optimizer: torch.optim.Optimizer,
    loss_fn: Union[Callable, torch.nn.Module],
    device: Optional[Union[str, torch.device]] = None,
    non_blocking: bool = False,
    prepare_batch: Callable = _prepare_batch,
    output_transform: Callable = lambda x, y, y_pred, loss: loss.item(),
) -> Engine:
    """
    Factory function for creating a trainer for supervised models.

    Args:
        model (`torch.nn.Module`): the model to train.
        optimizer (`torch.optim.Optimizer`): the optimizer to use.
        loss_fn (torch.nn loss function): the loss function to use.
        device (str, optional): device type specification (default: None).
            Applies to batches after starting the engine. Model *will not* be moved.
            Device can be CPU, GPU or TPU.
        non_blocking (bool, optional): if True and this copy is between CPU and GPU, the copy may occur asynchronously
            with respect to the host. For other cases, this argument has no effect.
        prepare_batch (callable, optional): function that receives `batch`, `device`, `non_blocking` and outputs
            tuple of tensors `(batch_x, batch_y)`.
        output_transform (callable, optional): function that receives 'x', 'y', 'y_pred', 'loss' and returns value
            to be assigned to engine's state.output after each iteration. Default is returning `loss.item()`.

    Note:
        `engine.state.output` for this engine is defind by `output_transform` parameter and is the loss
        of the processed batch by default.

    .. warning::

        The internal use of `device` has changed.
        `device` will now *only* be used to move the input data to the correct device.
        The `model` should be moved by the user before creating an optimizer.

        For more information see:

        * `PyTorch Documentation <https://pytorch.org/docs/stable/optim.html#constructing-it>`_
        * `PyTorch's Explanation <https://github.com/pytorch/pytorch/issues/7844#issuecomment-503713840>`_

    Returns:
        Engine: a trainer engine with supervised update function.
    """

    device_type = device.type if isinstance(device, torch.device) else device
    on_tpu = "xla" in device_type if device_type is not None else False

    if on_tpu:
        try:
            import torch_xla.core.xla_model as xm
        except ImportError:
            raise RuntimeError("In order to run on TPU, please install PyTorch XLA")

    def _update(engine: Engine, batch: Sequence[torch.Tensor]) -> Union[Any, Tuple[torch.Tensor]]:
        model.train()
        optimizer.zero_grad()
        x, y = prepare_batch(batch, device=device, non_blocking=non_blocking)
        y_pred = model(x)
        loss = loss_fn(y_pred, y)
        loss.backward()

        if on_tpu:
            xm.optimizer_step(optimizer, barrier=True)
        else:
            optimizer.step()

        return output_transform(x, y, y_pred, loss)

    trainer = Engine(_update)

    return trainer

def create_supervised_evaluator(
    model: torch.nn.Module,
    metrics: Optional[Dict[str, Metric]] = None,
    device: Optional[Union[str, torch.device]] = None,
    non_blocking: bool = False,
    prepare_batch: Callable = _prepare_batch,
    output_transform: Callable = lambda x, y, y_pred: (y_pred, y),
) -> Engine:
    """
    Factory function for creating an evaluator for supervised models.

    Args:
        model (`torch.nn.Module`): the model to train.
        metrics (dict of str - :class:`~ignite.metrics.Metric`): a map of metric names to Metrics.
        device (str, optional): device type specification (default: None).
            Applies to batches after starting the engine. Model *will not* be moved.
        non_blocking (bool, optional): if True and this copy is between CPU and GPU, the copy may occur asynchronously
            with respect to the host. For other cases, this argument has no effect.
        prepare_batch (callable, optional): function that receives `batch`, `device`, `non_blocking` and outputs
            tuple of tensors `(batch_x, batch_y)`.
        output_transform (callable, optional): function that receives 'x', 'y', 'y_pred' and returns value
            to be assigned to engine's state.output after each iteration. Default is returning `(y_pred, y,)` which fits
            output expected by metrics. If you change it you should use `output_transform` in metrics.

    Note:
        `engine.state.output` for this engine is defind by `output_transform` parameter and is
        a tuple of `(batch_pred, batch_y)` by default.

    .. warning::

        The internal use of `device` has changed.
        `device` will now *only* be used to move the input data to the correct device.
        The `model` should be moved by the user before creating an optimizer.

        For more information see:

        * `PyTorch Documentation <https://pytorch.org/docs/stable/optim.html#constructing-it>`_
        * `PyTorch's Explanation <https://github.com/pytorch/pytorch/issues/7844#issuecomment-503713840>`_

    Returns:
        Engine: an evaluator engine with supervised inference function.
    """
    metrics = metrics or {}

    def _inference(engine: Engine, batch: Sequence[torch.Tensor]) -> Union[Any, Tuple[torch.Tensor]]:
        model.eval()
        with torch.no_grad():
            x, y = prepare_batch(batch, device=device, non_blocking=non_blocking)
            y_pred = model(x)
            return output_transform(x, y, y_pred)

    evaluator = Engine(_inference)

    for name, metric in metrics.items():
        metric.attach(evaluator, name)

    return evaluator


#!/usr/bin/env python
# -*- coding: utf-8 -*-
from cleave import server

class MyServer(server.BaseServer):
    """
    My HTTP Server
    """
    def client_handler(self, client):
        """
        Handles a client connection
        :param client: server.BaseClient
        :return: None
        """
        client.send('HTTP/1.1 200 OK\n')
        client.send('Content-Type: text/html; charset=utf-8\n\n')

        client.send('
Hello world
')

        client.send('
My Address:
')
        client.send('
{}:{}
'.format(client.addr[0], client.addr[1]))

        client.send('
Request body:
')
        client.send('
{}
'.format(client.message))

        client.send('
By Cleave Server 0.13 Beta')

if __name__ == '__main__':
    MyServer(port=80)


from torch import nn
import torch as tc
import numpy as np
import BasicFun as bf
import time
import os
import sys
from termcolor import cprint
import matplotlib
from matplotlib.pyplot import plot, savefig, figure
from TensorNetworkExpasion import TTN_basic, Vectorization, TTN_Pool_2by2to1, \
    num_correct, load_tensor_network, save_tensor_network,\
    test_accuracy_mnist, pre_process_dataset, Attention_FC, Attention_Con2d, \
    TTN_Pool_2xto1, TTN_Pool_2yto1, TTN_ConvTI_2by2to1, TTN_PoolTI_2by2to1

# matplotlib.use('Agg')

def Paras_VL_CNN_BTN_Collected1chg1():
    para = parameter_default()
    para['TN'] = 'VL_CNN_BTN_Collected1chg1'
    para['batch_size'] = 600
    para['d'] = 4
    para['chi'] = 24
    para['feature_map'] = 'cos_sin'
    para['normalize_tensors'] = 'norm2'
    para['update_way'] = 'rotate'

    para['mps_init'] = 'randn'
    para['Lagrangian_way'] = 0
    para['Lagrangian'] = None
    para['check_time'] = 5
    para['save_time'] = 1000
    para['it_time'] = 1000
    para['lr'] = [1e-4, 2e-2]
    return para

class VL_CNN_BTN_Collected1chg1_BP(TTN_basic):
    """
                              train_acc       test_acc
    MNIST(d=4,chi=24)
    f-MNIST(d=4,chi=24)
    """

    def __init__(self, para_tn, tensors=None):
        super(VL_CNN_BTN_Collected1chg1_BP, self).__init__(num_layers=6)
        self.f_map = para_tn['feature_map']
        add_bias = False
        pre_process_tensors = 'square'  # 'normalize', 'softmax', 'square'
        self.layer0 = nn.Sequential(
            nn.Conv2d(1, 8, kernel_size=3),  # 26*26
            nn.LayerNorm([8, 26, 26], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 13*13
        ).to(device=para_tn['device'])
        self.layer1 = nn.Sequential(
            nn.Conv2d(8, 32, kernel_size=4),  # 10*10
            nn.LayerNorm([32, 10, 10], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 5*5
        ).to(device=para_tn['device'])
        self.layer2 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=2),  # 4*4
            nn.LayerNorm([64, 4, 4], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 2*2
        ).to(device=para_tn['device'])

        self.att = Attention_FC(64*4, 16, para_tn['device'])

        self.layer3 = TTN_Pool_2by2to1(
            1, 1, 4, 4, para_tn['d'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer4 = TTN_Pool_2by2to1(
            1, 1, 2, 2, para_tn['chi'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer5 = TTN_Pool_2by2to1(
            1, 1, 1, 1, para_tn['chi'], para_tn['channel'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.input_tensors(tensors)

    def forward(self, x, train=True):
        eps_mask = 0.005
        num = x.shape[0]
        x = x.reshape(-1, 1, 28, 28)
        for n in range(6):
            if n == 3:
                x = self.att(x.reshape(num, -1))
                x = x.reshape(-1, 4)
                x = nn.Softmax(dim=1)(x)
                x = x.reshape(num, 8, 8, 4, 1).permute(
                    0, 4, 3, 1, 2)

                x = mask_x(x, eps_mask, train)
            x = eval('self.layer' + str(n) + '(x)')
            if n in [3, 4, 5]:
                x = mask_x(x, eps_mask, train)
        # print(x.sum(dim=1))
        return x.squeeze()

def Paras_VL_CNN_BTN_Collected1chg2():
    para = parameter_default()
    para['TN'] = 'VL_CNN_BTN_Collected1chg2'
    para['batch_size'] = 600
    para['d'] = 4
    para['chi'] = 24
    para['feature_map'] = 'cos_sin'
    para['normalize_tensors'] = 'norm2'
    para['update_way'] = 'rotate'

    para['mps_init'] = 'randn'
    para['Lagrangian_way'] = 0
    para['Lagrangian'] = None
    para['check_time'] = 5
    para['save_time'] = 1000
    para['it_time'] = 1000
    para['lr'] = [1e-4, 2e-2]
    return para

class VL_CNN_BTN_Collected1chg2_BP(TTN_basic):
    """
                              train_acc       test_acc
    MNIST(d=4,chi=24)
    f-MNIST(d=4,chi=24)
    """

    def __init__(self, para_tn, tensors=None):
        super(VL_CNN_BTN_Collected1chg2_BP, self).__init__(num_layers=6)
        self.f_map = para_tn['feature_map']
        add_bias = False
        pre_process_tensors = 'square'  # 'normalize', 'softmax', 'square'
        self.layer0 = nn.Sequential(
            nn.Conv2d(1, 8, kernel_size=3),  # 26*26
            nn.LayerNorm([8, 26, 26], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 13*13
        ).to(device=para_tn['device'])
        self.layer1 = nn.Sequential(
            nn.Conv2d(8, 32, kernel_size=4),  # 10*10
            nn.LayerNorm([32, 10, 10], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 5*5
        ).to(device=para_tn['device'])
        self.layer2 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=2),  # 4*4
            nn.LayerNorm([64, 4, 4], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 2*2
        ).to(device=para_tn['device'])

        self.layer3 = TTN_Pool_2by2to1(
            1, 1, 4, 4, para_tn['d'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer4 = TTN_Pool_2by2to1(
            1, 1, 2, 2, para_tn['chi'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer5 = TTN_Pool_2by2to1(
            1, 1, 1, 1, para_tn['chi'], para_tn['channel'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.input_tensors(tensors)

    def forward(self, x, train=True):
        eps_mask = 0.005
        num = x.shape[0]
        x = x.reshape(-1, 1, 28, 28)
        for n in range(6):
            if n == 3:
                x = x.reshape(-1, 4)
                x = nn.Softmax(dim=1)(x)
                x = x.reshape(num, 8, 8, 4, 1).permute(
                    0, 4, 3, 1, 2)

                x = mask_x(x, eps_mask, train)
            x = eval('self.layer' + str(n) + '(x)')
            if n in [3, 4, 5]:
                x = mask_x(x, eps_mask, train)
        # print(x.sum(dim=1))
        return x.squeeze()

def Paras_VL_CNN_BTN_Collected1chg3():
    para = parameter_default()
    para['TN'] = 'VL_CNN_BTN_Collected1chg3'
    para['batch_size'] = 600
    para['d'] = 4
    para['chi'] = 24
    para['feature_map'] = 'cos_sin'
    para['normalize_tensors'] = 'norm2'
    para['update_way'] = 'rotate'

    para['mps_init'] = 'randn'
    para['Lagrangian_way'] = 0
    para['Lagrangian'] = None
    para['check_time'] = 5
    para['save_time'] = 1000
    para['it_time'] = 1000
    para['lr'] = [1e-4, 2e-2]
    return para

class VL_CNN_BTN_Collected1chg3_BP(TTN_basic):
    """
                              train_acc       test_acc
    MNIST(d=4,chi=24)
    f-MNIST(d=4,chi=24)
    """
    def __init__(self, para_tn, tensors=None):
        super(VL_CNN_BTN_Collected1chg3_BP, self).__init__(num_layers=6)
        theta = 1
        self.f_map = para_tn['feature_map']
        add_bias = False
        pre_process_tensors = 'square'   # 'normalize', 'softmax', 'square'
        self.layer0 = nn.Sequential(
            nn.Conv2d(1, 8, kernel_size=3),  # 26*26
            nn.LayerNorm([8, 26, 26], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 13*13
        ).to(device=para_tn['device'])
        self.layer1 = nn.Sequential(
            nn.Conv2d(8, 32, kernel_size=4),  # 10*10
            nn.LayerNorm([32, 10, 10], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 5*5
        ).to(device=para_tn['device'])
        self.layer2 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=2),  # 4*4
            nn.LayerNorm([64, 4, 4], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 2*2
        ).to(device=para_tn['device'])

        self.layer3 = TTN_Pool_2by2to1(
            1, 1, 4, 4, para_tn['d'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer4 = TTN_Pool_2by2to1(
            1, 1, 2, 2, para_tn['chi'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer5 = TTN_Pool_2by2to1(
            1, 1, 1, 1, para_tn['chi'], para_tn['channel'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.input_tensors(tensors)

    def forward(self, x, train=True):
        eps_mask = 0.01
        num = x.shape[0]
        x = x.reshape(-1, 1, 28, 28)
        for n in range(6):
            if n == 3:
                x = x.reshape(-1, 4)
                x = nn.Softmax(dim=1)(x)
                x = x.reshape(num, 8, 8, 4, 1).permute(
                    0, 4, 3, 1, 2)

                x = mask_x(x, eps_mask, train)
            x = eval('self.layer' + str(n) + '(x)')
            if n in [3, 4]:
                x = mask_x(x, eps_mask, train)
        # print(x.sum(dim=1))
        return x.squeeze()

def Paras_VL_CNN_BTN_Collected1chg4():
    para = parameter_default()
    para['TN'] = 'VL_CNN_BTN_Collected1chg4'
    para['batch_size'] = 600
    para['d'] = 4
    para['chi'] = 24
    para['feature_map'] = 'cos_sin'
    para['normalize_tensors'] = 'norm2'
    para['update_way'] = 'rotate'

    para['mps_init'] = 'randn'
    para['Lagrangian_way'] = 0
    para['Lagrangian'] = None
    para['check_time'] = 5
    para['save_time'] = 1000
    para['it_time'] = 1000
    para['lr'] = [1e-4, 2e-2]
    return para

class VL_CNN_BTN_Collected1chg4_BP(TTN_basic):
    """
                              train_acc       test_acc
    MNIST(d=4,chi=24)
    f-MNIST(d=4,chi=24)
    """
    def __init__(self, para_tn, tensors=None):
        super(VL_CNN_BTN_Collected1chg4_BP, self).__init__(num_layers=6)
        theta = 1
        self.f_map = para_tn['feature_map']
        add_bias = False
        pre_process_tensors = 'square'   # 'normalize', 'softmax', 'square'
        self.layer0 = nn.Sequential(
            nn.Conv2d(1, 8, kernel_size=3),  # 26*26
            nn.LayerNorm([8, 26, 26], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 13*13
        ).to(device=para_tn['device'])
        self.layer1 = nn.Sequential(
            nn.Conv2d(8, 32, kernel_size=4),  # 10*10
            nn.LayerNorm([32, 10, 10], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 5*5
        ).to(device=para_tn['device'])
        self.layer2 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=2),  # 4*4
            nn.LayerNorm([64, 4, 4], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 2*2
        ).to(device=para_tn['device'])

        self.layer3 = TTN_Pool_2by2to1(
            1, 1, 4, 4, para_tn['d'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer4 = TTN_Pool_2by2to1(
            1, 1, 2, 2, para_tn['chi'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer5 = TTN_Pool_2by2to1(
            1, 1, 1, 1, para_tn['chi'], para_tn['channel'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.input_tensors(tensors)

    def forward(self, x, train=True):
        eps_mask = 0.005
        num = x.shape[0]
        x = x.reshape(-1, 1, 28, 28)
        for n in range(6):
            if n == 3:
                x = x.reshape(-1, 4)
                x = nn.Softmax(dim=1)(x)
                x = x.reshape(num, 8, 8, 4, 1).permute(
                    0, 4, 3, 1, 2)

                x = mask_x(x, eps_mask, train)
            x = eval('self.layer' + str(n) + '(x)')
            if n in [3, 4]:
                x = mask_x(x, eps_mask, train)
        # print(x.sum(dim=1))
        return x.squeeze()

def Paras_VL_CNN_BTN_Collected1chg5():
    para = parameter_default()
    para['TN'] = 'VL_CNN_BTN_Collected1chg5'
    para['batch_size'] = 600
    para['d'] = 4
    para['chi'] = 24
    para['feature_map'] = 'cos_sin'
    para['normalize_tensors'] = 'norm2'
    para['update_way'] = 'rotate'

    para['mps_init'] = 'randn'
    para['Lagrangian_way'] = 0
    para['Lagrangian'] = None
    para['check_time'] = 5
    para['save_time'] = 1000
    para['it_time'] = 1000
    para['lr'] = [1e-4, 2e-2]
    return para

class VL_CNN_BTN_Collected1chg5_BP(TTN_basic):
    """
                              train_acc       test_acc
    MNIST(d=4,chi=24)
    f-MNIST(d=4,chi=24)
    """

    def __init__(self, para_tn, tensors=None):
        super(VL_CNN_BTN_Collected1chg5_BP, self).__init__(num_layers=6)
        theta = 1
        self.f_map = para_tn['feature_map']
        add_bias = False
        pre_process_tensors = 'square'  # 'normalize', 'softmax', 'square'
        self.layer0 = nn.Sequential(
            nn.Conv2d(1, 8, kernel_size=3),  # 26*26
            nn.LayerNorm([8, 26, 26], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 13*13
        ).to(device=para_tn['device'])
        self.layer1 = nn.Sequential(
            nn.Conv2d(8, 32, kernel_size=4),  # 10*10
            nn.LayerNorm([32, 10, 10], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 5*5
        ).to(device=para_tn['device'])
        self.layer2 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=2),  # 4*4
            nn.LayerNorm([64, 4, 4], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 2*2
        ).to(device=para_tn['device'])

        self.layer3 = TTN_Pool_2by2to1(
            1, 1, 4, 4, para_tn['d'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer4 = TTN_Pool_2by2to1(
            1, 1, 2, 2, para_tn['chi'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer5 = TTN_Pool_2by2to1(
            1, 1, 1, 1, para_tn['chi'], para_tn['channel'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.input_tensors(tensors)

    def forward(self, x, train=True):
        eps_mask = 0.02
        num = x.shape[0]
        x = x.reshape(-1, 1, 28, 28)
        for n in range(6):
            if n == 3:
                x = x.reshape(-1, 4)
                x = nn.Softmax(dim=1)(x)
                x = x.reshape(num, 8, 8, 4, 1).permute(
                    0, 4, 3, 1, 2)

                x = mask_x(x, eps_mask, train)
            x = eval('self.layer' + str(n) + '(x)')
            if n in [3, 4, 5]:
                x = mask_x(x, eps_mask, train)
        # print(x.sum(dim=1))
        return x.squeeze()

# ==========================================================
def tn_multi_classifier_CNNBTN_mnist(para=None):
    logger = bf.logger(para['log_name']+'.log', level='info')
    log = logger.logger.info
    t0 = time.time()
    if para is None:
        para = parameter_default()
    para = make_para_consistent(para)
    log('=' * 15)
    log('Using device: ' + str(para['device']))
    log('=' * 15)
    bf.print_dict(para)

    labels2mat = (para['loss_func'] == 'MSELoss')
    if para['TN'] == 'MPS':
        data_dim = 2
    else:
        data_dim = 5
    train_loader, test_loader = bf.load_mnist_and_batch(
        para['dataset'], para['classes'], para['num_samples'], None, para['batch_size'],
        data_dim=data_dim, labels2mat=labels2mat, channel=len(para['classes']),
        project_name=para['project'], dev=para['device'])

    train_loader, train_num_tot = pre_process_dataset(
        train_loader, para, para['device'])
    test_loader, test_num_tot = pre_process_dataset(
        test_loader, para, para['device'])

    img = train_loader[7][0].reshape(train_loader[3][0].shape[0], -1)
    img = img[3, :].reshape(28, 28)
    matplotlib.pyplot.imshow(img.cpu())
    matplotlib.pyplot.show()
    input()

    num_batch_train = len(train_loader)
    log('Num of training samples:\t' + str(train_num_tot))
    log('Num of testing samples:\t' + str(test_num_tot))
    log('Num of training batches:\t' + str(num_batch_train))
    log('Num of features:\t' + str(para['length']))
    log('Dataset finish processed...')

    loss_func = tc.nn.CrossEntropyLoss()

    tn = eval(para['TN'] + '_BP(para)')
    info = dict()
    info['train_acc'] = list()
    info['train_loss'] = list()
    info['test_acc'] = list()
    info['norm_coeff'] = list()
    if para['normalize_tensors'] is not None:
        tn.normalize_all_tensors(para['normalize_tensors'])

    nc = test_accuracy_mnist(tn, test_loader, para)
    log('Initially, we have test acc = ' + str(nc / test_num_tot))

    parameters_cnn = nn.ParameterList()
    parameters_btn = nn.ParameterList()
    for x in tn.parameters():
        if x.ndimension() in [7, 9]:
            parameters_btn.append(x)
        else:
            parameters_cnn.append(x)

    if parameters_cnn.__len__() > 0:
        optimizer_cnn = tc.optim.Adam(parameters_cnn, lr=para['lr'][0])
    if parameters_btn.__len__() > 0:
        optimizer_btn = tc.optim.Adam(parameters_btn, lr=para['lr'][1])

    log('Start training...')
    log('[Note: data will be save at: ' + para['data_path'] + ']')
    coeff_norm = 0
    if para['if_test']:
        titles = 'Epoch \t train_loss \t train_acc \t test_acc \t norm_coeff'
    else:
        titles = 'Epoch \t train_loss \t train_acc \t norm_coeff'
    log(titles)

    for t in range(para['it_time']):
        t_loop = time.time()
        train_loss = 0
        nc = 0
        if (num_batch_train > 1) and (t > 0):
            train_loader = bf.re_batch_data_loader(train_loader)
        for imgs, labels in train_loader:
            imgs, labels = imgs.to(para['device']), labels.to(para['device'])

            y = tn(imgs)
            loss = loss_func(y, labels)
            with tc.no_grad():
                train_loss += loss.data.item()

            loss.backward()

            for x in tn.parameters():
                if x.ndimension() in [7, 9]:
                    s = x.shape
                    # put grad in tangent space
                    inner = tc.einsum('ac,ac->a', x.data.view(-1, s[-1]),
                                      x.grad.data.view(-1, s[-1]))
                    grad = x.grad.data.view(-1, s[-1]) - tc.einsum(
                        'a,ab->ab', inner, x.data.view(-1, s[-1]))
                    # normalize grad
                    norm = grad.norm(dim=1, p=2) + 1e-12
                    grad = tc.einsum('ab,a->ab', grad, 1 / norm)
                    # print(tc.einsum('ac,ac->a', grad, x.data.view(-1, s[-1])))
                    x.grad.data = grad.view(s)

            if parameters_cnn.__len__() > 0:
                optimizer_cnn.step()
                optimizer_cnn.zero_grad()
            if parameters_btn.__len__() > 0:
                optimizer_btn.step()
                optimizer_btn.zero_grad()

            for x in tn.parameters():
                if x.ndimension() in [7, 9]:
                    s = x.shape
                    x = x.view(-1, s[-1])
                    norm = x.data.norm(
                        dim=1, p=2)
                    x.data[:, :] = tc.einsum(
                        'ab,a->ab', x.data, 1 / norm)
                    x.data = x.data.view(s)

            if ((t + 1) % para['check_time']) == 0:
                nc0, _ = num_correct(labels, y.data)
                nc += nc0
        if ((t + 1) % para['check_time']) == 0:
            info['train_acc'].append(nc / train_num_tot)
            info['train_loss'].append(train_loss)
            info['norm_coeff'].append(coeff_norm)
            message = str(t + 1) + ': '
            message += '\t %.6g' % info['train_loss'][-1]
            message += '\t %.6g' % info['train_acc'][-1]
            if para['if_test']:
                nc = test_accuracy_mnist(
                    tn, test_loader, para)
                info['test_acc'].append(nc / test_num_tot)
                message += '\t %.6g' % info['test_acc'][-1]
            message += '\t %.6g' % info['norm_coeff'][-1]
            log(message)
        if ((t+1) % para['save_time']) == 0:
            if (train_loss == float('nan')) or (train_loss == float('inf')):
                cprint('DO NOT save MPS since NAN/INF appears', color='red')
                sys.exit(1)
            else:
                info['time_1loop'] = time.time() - t_loop
                save_tensor_network(tn, para, info,
                                        para['data_path'], para['data_exp'])
                log('MPS saved: time cost per epoch = ' + str(info['time_1loop']))
                log(titles)
    x = np.arange(para['it_time'])
    fig = figure()
    plot(x, info['test_acc'])
    savefig('../results/' + para['TN'] + '_test_acc.png')

    info['time_tot'] = time.time() - t0
    log('Total time cost = ' + str(info['time_tot']))
    return para['data_path'], para['data_exp']

def parameter_default():
    para = dict()
    para['project'] = 'CNNBTNhybrid'
    para['which_TN_set'] = 'tne'  # 'tne' or 'ctnn'
    para['TN'] = 'MPS'

    para['dataset'] = 'fashion-mnist'
    para['classes'] = list(range(10))
    para['num_samples'] = ['all'] * para['classes'].__len__()
    para['batch_size'] = 3000

    para['binary_imgs'] = False
    para['cut_size'] = [28, 28]
    para['img_size'] = [28, 28]
    # to feature cut-off; not usable yet
    para['update_f_index'] = False
    para['tol_cut_f'] = 1e-12

    para['it_time'] = 200
    para['lr'] = [1e-4, 1e-2]
    para['d'] = 2
    para['chi'] = 2

    para['linear_gauss_noise'] = None
    para['pre_normalize_mps'] = 1
    para['normalize_mps'] = False
    para['optimizer'] = 'Adam'
    para['mps_init'] = 'No.1'
    para['feature_map'] = 'taylor'
    para['feature_theta'] = 1
    para['activate_fun'] = None
    para['activate_fun_final'] = None
    para['Lagrangian'] = None
    para['Lagrangian_way'] = 0
    para['norm_p'] = 1
    para['loss_func'] = 'CrossEntropyLoss'  # MSELoss, CrossEntropyLoss, NLLLoss

    para['check_time'] = 2
    para['save_time'] = 20
    para['if_test'] = True
    para['if_load'] = True
    para['if_load_smaller_chi'] = True
    para['clear_history'] = False
    para['normalize_tensors'] = None
    para['update_way'] = 'bp'
    para['multi_gpu_parallel'] = False

    para['log_name'] = 'record'
    para['device'] = 'cuda'

    para = make_para_consistent(para)
    return para

def make_para_consistent(para):
    if 'TN' not in para:
        para['TN'] = 'MPS'
    if 'norm_p' not in para:
        para['norm_p'] = 1
    if 'binary_imgs' not in para:
        para['binary_imgs'] = False
    if para['TN'] != 'MPS':
        para['normalize_mps'] = False
        para['activate_fun'] = None
        para['activate_fun_final'] = None
    para['data_path'] = './'
    if para['feature_map'] == 'fold_2d_order1':
        para['img_size'] = [round(para['img_size'][0]/2),
                            round(para['img_size'][1]/2)]
    if para['feature_map'].lower() in ['normalized_linear',
                                       'relsig', 'tansig', 'vsigmoid']:
        if para['d'] != 2:
            bf.warning('Warning: Inconsistent para[\'d\']=%g to '
                       'feature map. Please check...' % para['d'])
            para['d'] = 2
    if para['feature_map'].lower() == 'reltansig':
        if para['d'] != 3:
            bf.warning('Warning: Inconsistent para[\'d\']=%g to '
                       'feature map. Please check...' % para['d'])
            para['d'] = 3
    para['length'] = para['img_size'][0] * para['img_size'][1]
    if 'feature_index' not in para:
        para['feature_index'] = None
    elif para['feature_index'] is not None:
        if len(para['feature_index']) > para['length']:
            bf.warning('Error: length > len(feature_index).')
            sys.exit(1)
        elif max(para['feature_index']) > (para['length'] - 1):
            bf.warning('Error: feature_index.max() > len(feature_index).')
            sys.exit(1)
        else:
            para['length'] = len(para['feature_index'])
    para['channel'] = len(para['classes'])
    para['data_exp'] = data_exp_to_save_mps(para)
    if (para['device'] != 'cpu') and (not tc.cuda.is_available()):
        para['device'] = 'cpu'
        bf.warning('Cuda is not available in the device...')
        bf.warning('Changed to \'cpu\' instead...')
    return para

def data_exp_to_save_mps(para):
    exp = para['TN'].upper() + '_L' + str(para['length']) + '_d' + str(para['d']) + '_chi' + \
               str(para['chi']) + '_classes' + str(para['classes']) + '_' + \
               para['feature_map'] + '_' + para['dataset'].upper()
    if para['dataset'].lower() in ['mnist', 'fashion-mnist', 'fashionmnist']:
        if (para['cut_size'][0] != 28) or (para['cut_size'][1] != 28):
            exp += ('_size' + str(para['cut_size']))
        if (para['img_size'][0] != 28) or (para['img_size'][1] != 28):
            exp += str(para['img_size'])
    elif para['dataset'].lower() in ['cifar10', 'cifar-10']:
        if (para['cut_size'][0] != 32) or (para['cut_size'][1] != 32):
            exp += ('_size' + str(para['cut_size']))
        if (para['img_size'][0] != 32) or (para['img_size'][1] != 32):
            exp += str(para['img_size'])
    if 'feature_index' in para:
        if para['feature_index'] is not None:
            exp += '_FindexedNum' + str(len(para['feature_index']))
    if para['binary_imgs']:
        exp += 'binary'
    return exp

def load_saved_tn_smaller_chi_d(para, path1=None):
    if para['if_load']:
        path = './data/' + para['TN'] + '/'
        exp = data_exp_to_save_mps(para)
        mps_file = os.path.join(path, exp)
        if os.path.isfile(mps_file):
            message = 'Load existing ' + para['TN'] + ' data...'
            mps, info, _ = load_tensor_network(mps_file, para)
            return mps, info, message
        elif para['if_load_smaller_chi']:
            if path1 is None:
                path1 = './data/' + para['TN'] + '_saved/'
            chi0 = para['chi']
            d0 = para['d']
            for d in range(d0, 1, -1):
                for chi in range(chi0, 1, -1):
                    para['d'] = d
                    para['chi'] = chi
                    exp = data_exp_to_save_mps(para)
                    mps_file = os.path.join(path1, exp)
                    if os.path.isfile(mps_file):
                        message = 'Load existing ' + para['TN'] + ' with (d, chi) = ' + \
                                  str((para['d'], para['chi']))
                        para['chi'], para['d'] = chi0, d0
                        mps, info, _ = load_tensor_network(
                            mps_file, para)
                        return mps, info, message
            message = 'No existing smaller-chi/d ' + \
                      para['TN'] + ' found...\n ' \
                                   'Create new ' + para['TN'] + ' data ...'
            para['chi'], para['d'] = chi0, d0
            return None, None, message
        else:
            message = 'No existing ' + para['TN'] + ' found...\n Create new ' + \
                      para['TN'] + ' data ...'
            return None, None, message
    else:
        return None, None, 'Create new ' + para['TN'] + ' data ...'

def mask_x(x, eps_mask, train):
    if train:
        mask = (x.data > eps_mask)
        x = x * mask + 1e-12
        s = x.shape
        norm = x.data.permute(0, 1, 3, 4, 2).reshape(-1, s[2]).norm(dim=1)
        norm = norm.reshape(s[0], s[3], s[4])
        x = tc.einsum('ncdxy,nxy->ncdxy', x, 1 / norm)
    return x

# ==========================================================================================
# Collected hybrid models

def Paras_VL_CNN_BTN_Collected1():
    para = parameter_default()
    para['TN'] = 'VL_CNN_BTN_Collected1'
    para['batch_size'] = 600
    para['d'] = 4
    para['chi'] = 24
    para['feature_map'] = 'cos_sin'
    para['normalize_tensors'] = 'norm2'
    para['update_way'] = 'rotate'

    para['mps_init'] = 'randn'
    para['Lagrangian_way'] = 0
    para['Lagrangian'] = None
    para['check_time'] = 5
    para['save_time'] = 1000
    para['it_time'] = 1000
    para['lr'] = [1e-4, 2e-2]
    return para

class VL_CNN_BTN_Collected1_BP(TTN_basic):
    """
                              train_acc       test_acc
    MNIST(d=4,chi=24)         0.999633        0.9887
    f-MNIST(d=4,chi=24)       0.971017        0.8966
    f-MNIST(d=4,chi=14)       0.971883	      0.8887
    """
    def __init__(self, para_tn, tensors=None):
        super(VL_CNN_BTN_Collected1_BP, self).__init__(num_layers=6)
        theta = 1
        self.f_map = para_tn['feature_map']
        add_bias = False
        pre_process_tensors = 'square'   # 'normalize', 'softmax', 'square'
        self.layer0 = nn.Sequential(
            nn.Conv2d(1, 8, kernel_size=3),  # 26*26
            nn.LayerNorm([8, 26, 26], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 13*13
        ).to(device=para_tn['device'])
        self.layer1 = nn.Sequential(
            nn.Conv2d(8, 32, kernel_size=4),  # 10*10
            nn.LayerNorm([32, 10, 10], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 5*5
        ).to(device=para_tn['device'])
        self.layer2 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=2),  # 4*4
            nn.LayerNorm([64, 4, 4], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 2*2
        ).to(device=para_tn['device'])

        self.layer3 = TTN_Pool_2by2to1(
            1, 1, 4, 4, para_tn['d'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer4 = TTN_Pool_2by2to1(
            1, 1, 2, 2, para_tn['chi'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer5 = TTN_Pool_2by2to1(
            1, 1, 1, 1, para_tn['chi'], para_tn['channel'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.input_tensors(tensors)

    def forward(self, x):
        num = x.shape[0]
        x = x.reshape(-1, 1, 28, 28)
        for n in range(6):
            if n == 3:
                x = x.reshape(-1, 4)
                x = nn.Softmax(dim=1)(x)
                x = x.reshape(num, 8, 8, 4, 1).permute(
                    0, 4, 3, 1, 2)
            x = eval('self.layer' + str(n) + '(x)')
        x = x.squeeze()
        # print(x.sum(dim=1))
        return x

def Paras_VL_CNN_BTN_Collected2():
    para = parameter_default()
    para['TN'] = 'CNN_BTN_Collected2'
    para['batch_size'] = 600
    para['d'] = 4
    para['chi'] = 24
    para['feature_map'] = 'cos_sin'
    para['normalize_tensors'] = 'norm2'
    para['update_way'] = 'rotate'

    para['mps_init'] = 'randn'
    para['Lagrangian_way'] = 0
    para['Lagrangian'] = None
    para['check_time'] = 5
    para['save_time'] = 1000
    para['it_time'] = 1000
    para['lr'] = [1e-4, 2e-2]
    return para

class VL_CNN_BTN_Collected2_BP(TTN_basic):
    """
                              train_acc       test_acc
    MNIST
    f-MNIST(d=4, chi=24)     0.971217        0.8858
    """

    def __init__(self, para_tn, tensors=None):
        super(VL_CNN_BTN_Collected2_BP, self).__init__(num_layers=6)
        theta = 1
        self.f_map = para_tn['feature_map']
        add_bias = False
        pre_process_tensors = 'square'  # 'normalize', 'softmax', 'square'
        self.layer0 = nn.Sequential(
            nn.Conv2d(1, 4, kernel_size=3),  # 26*26
            nn.LayerNorm([4, 26, 26], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.Conv2d(4, 8, kernel_size=3),  # 24*24
            nn.LayerNorm([8, 24, 24], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 12*12
        ).to(device=para_tn['device'])
        self.layer1 = nn.Sequential(
            nn.Conv2d(8, 32, kernel_size=3),  # 10*10
            nn.LayerNorm([32, 10, 10], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 5*5
        ).to(device=para_tn['device'])
        self.layer2 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=2),  # 4*4
            nn.LayerNorm([64, 4, 4], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 2*2
        ).to(device=para_tn['device'])

        self.layer3 = TTN_Pool_2xto1(
            1, 1, 32, 1, para_tn['d'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer4 = TTN_Pool_2xto1(
            1, 1, 16, 1, para_tn['chi'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer5 = TTN_Pool_2xto1(
            1, 1, 8, 1, para_tn['chi'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer6 = TTN_Pool_2xto1(
            1, 1, 4, 1, para_tn['chi'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer7 = TTN_Pool_2xto1(
            1, 1, 2, 1, para_tn['chi'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer8 = TTN_Pool_2xto1(
            1, 1, 1, 1, para_tn['chi'], para_tn['channel'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.input_tensors(tensors)

    def forward(self, x):
        num = x.shape[0]
        x = x.reshape(-1, 1, 28, 28)
        for n in range(9):
            if n == 3:
                x = x.reshape(-1, 4)
                x = nn.Softmax(dim=1)(x)
                x = x.reshape(num, 64, 1, 4, 1).permute(
                    0, 4, 3, 1, 2)
            x = eval('self.layer' + str(n) + '(x)')
        x = x.squeeze()
        # print(x.sum(dim=1))
        return x

def Paras_VL_CNN_BTN_Collected3():
    para = parameter_default()
    para['TN'] = 'VL_CNN_BTN_Collected3'
    para['batch_size'] = 400
    para['d'] = 4
    para['chi'] = 24
    para['feature_map'] = 'cos_sin'
    para['normalize_tensors'] = 'norm2'
    para['update_way'] = 'rotate'

    para['mps_init'] = 'randn'
    para['Lagrangian_way'] = 0
    para['Lagrangian'] = None
    para['check_time'] = 5
    para['save_time'] = 1000
    para['it_time'] = 1000
    para['lr'] = [1e-4, 2e-2]
    return para

class VL_CNN_BTN_Collected3_BP(TTN_basic):
    """
                              train_acc       test_acc
    MNIST
    f-MNIST(d=4, chi=24)      0.9768        0.8862
    """
    def __init__(self, para_tn, tensors=None):
        super(VL_CNN_BTN_Collected3_BP, self).__init__(num_layers=6)
        theta = 1
        self.f_map = para_tn['feature_map']
        add_bias = False
        pre_process_tensors = 'square'   # 'normalize', 'softmax', 'square'
        self.layer0 = nn.Sequential(
            nn.Conv2d(1, 8, kernel_size=3),  # 26*26
            nn.LayerNorm([8, 26, 26], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 13*13
        ).to(device=para_tn['device'])
        self.layer1 = nn.Sequential(
            nn.Conv2d(8, 32, kernel_size=4),  # 10*10
            nn.LayerNorm([32, 10, 10], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 5*5
        ).to(device=para_tn['device'])
        self.layer2 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=2),  # 4*4
            nn.LayerNorm([64, 4, 4], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 2*2
        ).to(device=para_tn['device'])

        self.layer3 = TTN_PoolTI_2by2to1(
            1, 1, para_tn['d'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer4 = TTN_Pool_2by2to1(
            1, 1, 2, 2, para_tn['chi'], para_tn['chi'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.layer5 = TTN_Pool_2by2to1(
            1, 1, 1, 1, para_tn['chi'], para_tn['channel'],
            para_tn['device'], ini_way=para_tn['mps_init'],
            if_pre_proc_T=pre_process_tensors, add_bias=add_bias)
        self.input_tensors(tensors)

    def forward(self, x):
        num = x.shape[0]
        x = x.reshape(-1, 1, 28, 28)
        for n in range(6):
            if n == 3:
                x = x.reshape(-1, 4)
                x = nn.Softmax(dim=1)(x)
                x = x.reshape(num, 8, 8, 4, 1).permute(
                    0, 4, 3, 1, 2)
            x = eval('self.layer' + str(n) + '(x)')
        x = x.squeeze()
        # print(x.sum(dim=1))
        return x

def Paras_VL_CNN():
    para = parameter_default()
    para['TN'] = 'VL_CNN'
    para['batch_size'] = 600
    para['normalize_tensors'] = 'norm2'

    para['mps_init'] = 'randn'
    para['check_time'] = 5
    para['save_time'] = 1000

    para['it_time'] = 1000
    para['lr'] = [1e-4, 2e-2]
    return para

class VL_CNN_BP(TTN_basic):
    """
                     train_acc   test_acc
    MNIST
    f-MNIST         0.962283        0.8917
    """
    def __init__(self, para_tn):
        super(VL_CNN_BP, self).__init__(num_layers=6)
        self.layer0 = nn.Sequential(
            nn.Conv2d(1, 8, kernel_size=3),  # 26*26
            nn.LayerNorm([8, 26, 26], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 13*13
        ).to(device=para_tn['device'])
        self.layer1 = nn.Sequential(
            nn.Conv2d(8, 32, kernel_size=4),  # 10*10
            nn.LayerNorm([32, 10, 10], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 5*5
        ).to(device=para_tn['device'])
        self.layer2 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=2),  # 4*4
            nn.LayerNorm([64, 4, 4], eps=1e-05, elementwise_affine=True),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2)  # 2*2
        ).to(device=para_tn['device'])
        self.layer3 = nn.Sequential(
            nn.Linear(64*4, 64),
            nn.ReLU(inplace=True),
            nn.Linear(64, para_tn['channel']),
            nn.Sigmoid()
        ).to(device=para_tn['device'])

    def forward(self, x):
        num = x.shape[0]
        x = x.reshape(-1, 1, 28, 28)
        for n in range(4):
            if n == 3:
                x = x.reshape(num, -1)
            x = eval('self.layer' + str(n) + '(x)')
        x = x.squeeze()
        # print(x.sum(dim=1))
        return x